Automated class transform
npx lebab --replace src --transform class
This commit is contained in:
@@ -41,60 +41,175 @@ import {createXYZ, extentFromProjection} from '../tilegrid.js';
|
||||
* @param {module:ol/source/BingMaps~Options=} options Bing Maps options.
|
||||
* @api
|
||||
*/
|
||||
const BingMaps = function(options) {
|
||||
class BingMaps {
|
||||
constructor(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : false;
|
||||
|
||||
TileImage.call(this, {
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: 'anonymous',
|
||||
opaque: true,
|
||||
projection: getProjection('EPSG:3857'),
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
state: SourceState.LOADING,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
tilePixelRatio: this.hidpi_ ? 2 : 1,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.culture_ = options.culture !== undefined ? options.culture : 'en-us';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.apiKey_ = options.key;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.imagerySet_ = options.imagerySet;
|
||||
|
||||
const url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
|
||||
this.imagerySet_ +
|
||||
'?uriScheme=https&include=ImageryProviders&key=' + this.apiKey_ +
|
||||
'&c=' + this.culture_;
|
||||
|
||||
requestJSONP(url, this.handleImageryMetadataResponse.bind(this), undefined,
|
||||
'jsonp');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* Get the api key used for this source.
|
||||
*
|
||||
* @return {string} The api key.
|
||||
* @api
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : false;
|
||||
|
||||
TileImage.call(this, {
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: 'anonymous',
|
||||
opaque: true,
|
||||
projection: getProjection('EPSG:3857'),
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
state: SourceState.LOADING,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
tilePixelRatio: this.hidpi_ ? 2 : 1,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
getApiKey() {
|
||||
return this.apiKey_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
* Get the imagery set associated with this source.
|
||||
*
|
||||
* @return {string} The imagery set.
|
||||
* @api
|
||||
*/
|
||||
this.culture_ = options.culture !== undefined ? options.culture : 'en-us';
|
||||
getImagerySet() {
|
||||
return this.imagerySet_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* @param {BingMapsImageryMetadataResponse} response Response.
|
||||
*/
|
||||
this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
|
||||
handleImageryMetadataResponse(response) {
|
||||
if (response.statusCode != 200 ||
|
||||
response.statusDescription != 'OK' ||
|
||||
response.authenticationResultCode != 'ValidCredentials' ||
|
||||
response.resourceSets.length != 1 ||
|
||||
response.resourceSets[0].resources.length != 1) {
|
||||
this.setState(SourceState.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.apiKey_ = options.key;
|
||||
const resource = response.resourceSets[0].resources[0];
|
||||
const maxZoom = this.maxZoom_ == -1 ? resource.zoomMax : this.maxZoom_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.imagerySet_ = options.imagerySet;
|
||||
const sourceProjection = this.getProjection();
|
||||
const extent = extentFromProjection(sourceProjection);
|
||||
const tileSize = resource.imageWidth == resource.imageHeight ?
|
||||
resource.imageWidth : [resource.imageWidth, resource.imageHeight];
|
||||
const tileGrid = createXYZ({
|
||||
extent: extent,
|
||||
minZoom: resource.zoomMin,
|
||||
maxZoom: maxZoom,
|
||||
tileSize: tileSize / (this.hidpi_ ? 2 : 1)
|
||||
});
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
const url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
|
||||
this.imagerySet_ +
|
||||
'?uriScheme=https&include=ImageryProviders&key=' + this.apiKey_ +
|
||||
'&c=' + this.culture_;
|
||||
const culture = this.culture_;
|
||||
const hidpi = this.hidpi_;
|
||||
this.tileUrlFunction = createFromTileUrlFunctions(
|
||||
resource.imageUrlSubdomains.map(function(subdomain) {
|
||||
const quadKeyTileCoord = [0, 0, 0];
|
||||
const imageUrl = resource.imageUrl
|
||||
.replace('{subdomain}', subdomain)
|
||||
.replace('{culture}', culture);
|
||||
return (
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
function(tileCoord, pixelRatio, projection) {
|
||||
if (!tileCoord) {
|
||||
return undefined;
|
||||
} else {
|
||||
createOrUpdate(tileCoord[0], tileCoord[1], -tileCoord[2] - 1, quadKeyTileCoord);
|
||||
let url = imageUrl;
|
||||
if (hidpi) {
|
||||
url += '&dpi=d1&device=mobile';
|
||||
}
|
||||
return url.replace('{quadkey}', quadKey(quadKeyTileCoord));
|
||||
}
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
requestJSONP(url, this.handleImageryMetadataResponse.bind(this), undefined,
|
||||
'jsonp');
|
||||
if (resource.imageryProviders) {
|
||||
const transform = getTransformFromProjections(
|
||||
getProjection('EPSG:4326'), this.getProjection());
|
||||
|
||||
};
|
||||
this.setAttributions(function(frameState) {
|
||||
const attributions = [];
|
||||
const zoom = frameState.viewState.zoom;
|
||||
resource.imageryProviders.map(function(imageryProvider) {
|
||||
let intersecting = false;
|
||||
const coverageAreas = imageryProvider.coverageAreas;
|
||||
for (let i = 0, ii = coverageAreas.length; i < ii; ++i) {
|
||||
const coverageArea = coverageAreas[i];
|
||||
if (zoom >= coverageArea.zoomMin && zoom <= coverageArea.zoomMax) {
|
||||
const bbox = coverageArea.bbox;
|
||||
const epsg4326Extent = [bbox[1], bbox[0], bbox[3], bbox[2]];
|
||||
const extent = applyTransform(epsg4326Extent, transform);
|
||||
if (intersects(extent, frameState.extent)) {
|
||||
intersecting = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intersecting) {
|
||||
attributions.push(imageryProvider.attribution);
|
||||
}
|
||||
});
|
||||
|
||||
attributions.push(TOS_ATTRIBUTION);
|
||||
return attributions;
|
||||
});
|
||||
}
|
||||
|
||||
this.setState(SourceState.READY);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(BingMaps, TileImage);
|
||||
|
||||
@@ -110,118 +225,4 @@ const TOS_ATTRIBUTION = '<a class="ol-attribution-bing-tos" ' +
|
||||
'Terms of Use</a>';
|
||||
|
||||
|
||||
/**
|
||||
* Get the api key used for this source.
|
||||
*
|
||||
* @return {string} The api key.
|
||||
* @api
|
||||
*/
|
||||
BingMaps.prototype.getApiKey = function() {
|
||||
return this.apiKey_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the imagery set associated with this source.
|
||||
*
|
||||
* @return {string} The imagery set.
|
||||
* @api
|
||||
*/
|
||||
BingMaps.prototype.getImagerySet = function() {
|
||||
return this.imagerySet_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {BingMapsImageryMetadataResponse} response Response.
|
||||
*/
|
||||
BingMaps.prototype.handleImageryMetadataResponse = function(response) {
|
||||
if (response.statusCode != 200 ||
|
||||
response.statusDescription != 'OK' ||
|
||||
response.authenticationResultCode != 'ValidCredentials' ||
|
||||
response.resourceSets.length != 1 ||
|
||||
response.resourceSets[0].resources.length != 1) {
|
||||
this.setState(SourceState.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
const resource = response.resourceSets[0].resources[0];
|
||||
const maxZoom = this.maxZoom_ == -1 ? resource.zoomMax : this.maxZoom_;
|
||||
|
||||
const sourceProjection = this.getProjection();
|
||||
const extent = extentFromProjection(sourceProjection);
|
||||
const tileSize = resource.imageWidth == resource.imageHeight ?
|
||||
resource.imageWidth : [resource.imageWidth, resource.imageHeight];
|
||||
const tileGrid = createXYZ({
|
||||
extent: extent,
|
||||
minZoom: resource.zoomMin,
|
||||
maxZoom: maxZoom,
|
||||
tileSize: tileSize / (this.hidpi_ ? 2 : 1)
|
||||
});
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
const culture = this.culture_;
|
||||
const hidpi = this.hidpi_;
|
||||
this.tileUrlFunction = createFromTileUrlFunctions(
|
||||
resource.imageUrlSubdomains.map(function(subdomain) {
|
||||
const quadKeyTileCoord = [0, 0, 0];
|
||||
const imageUrl = resource.imageUrl
|
||||
.replace('{subdomain}', subdomain)
|
||||
.replace('{culture}', culture);
|
||||
return (
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {string|undefined} Tile URL.
|
||||
*/
|
||||
function(tileCoord, pixelRatio, projection) {
|
||||
if (!tileCoord) {
|
||||
return undefined;
|
||||
} else {
|
||||
createOrUpdate(tileCoord[0], tileCoord[1], -tileCoord[2] - 1, quadKeyTileCoord);
|
||||
let url = imageUrl;
|
||||
if (hidpi) {
|
||||
url += '&dpi=d1&device=mobile';
|
||||
}
|
||||
return url.replace('{quadkey}', quadKey(quadKeyTileCoord));
|
||||
}
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
if (resource.imageryProviders) {
|
||||
const transform = getTransformFromProjections(
|
||||
getProjection('EPSG:4326'), this.getProjection());
|
||||
|
||||
this.setAttributions(function(frameState) {
|
||||
const attributions = [];
|
||||
const zoom = frameState.viewState.zoom;
|
||||
resource.imageryProviders.map(function(imageryProvider) {
|
||||
let intersecting = false;
|
||||
const coverageAreas = imageryProvider.coverageAreas;
|
||||
for (let i = 0, ii = coverageAreas.length; i < ii; ++i) {
|
||||
const coverageArea = coverageAreas[i];
|
||||
if (zoom >= coverageArea.zoomMin && zoom <= coverageArea.zoomMax) {
|
||||
const bbox = coverageArea.bbox;
|
||||
const epsg4326Extent = [bbox[1], bbox[0], bbox[3], bbox[2]];
|
||||
const extent = applyTransform(epsg4326Extent, transform);
|
||||
if (intersects(extent, frameState.extent)) {
|
||||
intersecting = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intersecting) {
|
||||
attributions.push(imageryProvider.attribution);
|
||||
}
|
||||
});
|
||||
|
||||
attributions.push(TOS_ATTRIBUTION);
|
||||
return attributions;
|
||||
});
|
||||
}
|
||||
|
||||
this.setState(SourceState.READY);
|
||||
};
|
||||
export default BingMaps;
|
||||
|
||||
@@ -40,152 +40,149 @@ import XYZ from '../source/XYZ.js';
|
||||
* @param {module:ol/source/CartoDB~Options=} options CartoDB options.
|
||||
* @api
|
||||
*/
|
||||
const CartoDB = function(options) {
|
||||
class CartoDB {
|
||||
constructor(options) {
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.account_ = options.account;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.mapId_ = options.map || '';
|
||||
|
||||
/**
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
this.config_ = options.config || {};
|
||||
|
||||
/**
|
||||
* @type {!Object.<string, CartoDBLayerInfo>}
|
||||
* @private
|
||||
*/
|
||||
this.templateCache_ = {};
|
||||
|
||||
XYZ.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
|
||||
minZoom: options.minZoom,
|
||||
projection: options.projection,
|
||||
state: SourceState.LOADING,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
this.initializeMap_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
* Returns the current config.
|
||||
* @return {!Object} The current configuration.
|
||||
* @api
|
||||
*/
|
||||
this.account_ = options.account;
|
||||
getConfig() {
|
||||
return this.config_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
* Updates the carto db config.
|
||||
* @param {Object} config a key-value lookup. Values will replace current values
|
||||
* in the config.
|
||||
* @api
|
||||
*/
|
||||
this.mapId_ = options.map || '';
|
||||
updateConfig(config) {
|
||||
assign(this.config_, config);
|
||||
this.initializeMap_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {!Object}
|
||||
* @private
|
||||
* Sets the CartoDB config
|
||||
* @param {Object} config In the case of anonymous maps, a CartoDB configuration
|
||||
* object.
|
||||
* If using named maps, a key-value lookup with the template parameters.
|
||||
* @api
|
||||
*/
|
||||
this.config_ = options.config || {};
|
||||
setConfig(config) {
|
||||
this.config_ = config || {};
|
||||
this.initializeMap_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {!Object.<string, CartoDBLayerInfo>}
|
||||
* Issue a request to initialize the CartoDB map.
|
||||
* @private
|
||||
*/
|
||||
this.templateCache_ = {};
|
||||
initializeMap_() {
|
||||
const paramHash = JSON.stringify(this.config_);
|
||||
if (this.templateCache_[paramHash]) {
|
||||
this.applyTemplate_(this.templateCache_[paramHash]);
|
||||
return;
|
||||
}
|
||||
let mapUrl = 'https://' + this.account_ + '.carto.com/api/v1/map';
|
||||
|
||||
XYZ.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
|
||||
minZoom: options.minZoom,
|
||||
projection: options.projection,
|
||||
state: SourceState.LOADING,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
this.initializeMap_();
|
||||
};
|
||||
if (this.mapId_) {
|
||||
mapUrl += '/named/' + this.mapId_;
|
||||
}
|
||||
|
||||
const client = new XMLHttpRequest();
|
||||
client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
|
||||
client.addEventListener('error', this.handleInitError_.bind(this));
|
||||
client.open('POST', mapUrl);
|
||||
client.setRequestHeader('Content-type', 'application/json');
|
||||
client.send(JSON.stringify(this.config_));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle map initialization response.
|
||||
* @param {string} paramHash a hash representing the parameter set that was used
|
||||
* for the request
|
||||
* @param {Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
handleInitResponse_(paramHash, event) {
|
||||
const client = /** @type {XMLHttpRequest} */ (event.target);
|
||||
// status will be 0 for file:// urls
|
||||
if (!client.status || client.status >= 200 && client.status < 300) {
|
||||
let response;
|
||||
try {
|
||||
response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
|
||||
} catch (err) {
|
||||
this.setState(SourceState.ERROR);
|
||||
return;
|
||||
}
|
||||
this.applyTemplate_(response);
|
||||
this.templateCache_[paramHash] = response;
|
||||
this.setState(SourceState.READY);
|
||||
} else {
|
||||
this.setState(SourceState.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event Event.
|
||||
*/
|
||||
handleInitError_(event) {
|
||||
this.setState(SourceState.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the new tile urls returned by carto db
|
||||
* @param {CartoDBLayerInfo} data Result of carto db call.
|
||||
* @private
|
||||
*/
|
||||
applyTemplate_(data) {
|
||||
const tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
|
||||
'/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
|
||||
this.setUrl(tilesUrl);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(CartoDB, XYZ);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current config.
|
||||
* @return {!Object} The current configuration.
|
||||
* @api
|
||||
*/
|
||||
CartoDB.prototype.getConfig = function() {
|
||||
return this.config_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates the carto db config.
|
||||
* @param {Object} config a key-value lookup. Values will replace current values
|
||||
* in the config.
|
||||
* @api
|
||||
*/
|
||||
CartoDB.prototype.updateConfig = function(config) {
|
||||
assign(this.config_, config);
|
||||
this.initializeMap_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the CartoDB config
|
||||
* @param {Object} config In the case of anonymous maps, a CartoDB configuration
|
||||
* object.
|
||||
* If using named maps, a key-value lookup with the template parameters.
|
||||
* @api
|
||||
*/
|
||||
CartoDB.prototype.setConfig = function(config) {
|
||||
this.config_ = config || {};
|
||||
this.initializeMap_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Issue a request to initialize the CartoDB map.
|
||||
* @private
|
||||
*/
|
||||
CartoDB.prototype.initializeMap_ = function() {
|
||||
const paramHash = JSON.stringify(this.config_);
|
||||
if (this.templateCache_[paramHash]) {
|
||||
this.applyTemplate_(this.templateCache_[paramHash]);
|
||||
return;
|
||||
}
|
||||
let mapUrl = 'https://' + this.account_ + '.carto.com/api/v1/map';
|
||||
|
||||
if (this.mapId_) {
|
||||
mapUrl += '/named/' + this.mapId_;
|
||||
}
|
||||
|
||||
const client = new XMLHttpRequest();
|
||||
client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
|
||||
client.addEventListener('error', this.handleInitError_.bind(this));
|
||||
client.open('POST', mapUrl);
|
||||
client.setRequestHeader('Content-type', 'application/json');
|
||||
client.send(JSON.stringify(this.config_));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle map initialization response.
|
||||
* @param {string} paramHash a hash representing the parameter set that was used
|
||||
* for the request
|
||||
* @param {Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
CartoDB.prototype.handleInitResponse_ = function(paramHash, event) {
|
||||
const client = /** @type {XMLHttpRequest} */ (event.target);
|
||||
// status will be 0 for file:// urls
|
||||
if (!client.status || client.status >= 200 && client.status < 300) {
|
||||
let response;
|
||||
try {
|
||||
response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
|
||||
} catch (err) {
|
||||
this.setState(SourceState.ERROR);
|
||||
return;
|
||||
}
|
||||
this.applyTemplate_(response);
|
||||
this.templateCache_[paramHash] = response;
|
||||
this.setState(SourceState.READY);
|
||||
} else {
|
||||
this.setState(SourceState.ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event Event.
|
||||
*/
|
||||
CartoDB.prototype.handleInitError_ = function(event) {
|
||||
this.setState(SourceState.ERROR);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply the new tile urls returned by carto db
|
||||
* @param {CartoDBLayerInfo} data Result of carto db call.
|
||||
* @private
|
||||
*/
|
||||
CartoDB.prototype.applyTemplate_ = function(data) {
|
||||
const tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
|
||||
'/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
|
||||
this.setUrl(tilesUrl);
|
||||
};
|
||||
export default CartoDB;
|
||||
|
||||
@@ -47,175 +47,172 @@ import VectorSource from '../source/Vector.js';
|
||||
* @extends {module:ol/source/Vector}
|
||||
* @api
|
||||
*/
|
||||
const Cluster = function(options) {
|
||||
VectorSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
class Cluster {
|
||||
constructor(options) {
|
||||
VectorSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @protected
|
||||
*/
|
||||
this.resolution = undefined;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @protected
|
||||
*/
|
||||
this.distance = options.distance !== undefined ? options.distance : 20;
|
||||
|
||||
/**
|
||||
* @type {Array.<module:ol/Feature>}
|
||||
* @protected
|
||||
*/
|
||||
this.features = [];
|
||||
|
||||
/**
|
||||
* @param {module:ol/Feature} feature Feature.
|
||||
* @return {module:ol/geom/Point} Cluster calculation point.
|
||||
* @protected
|
||||
*/
|
||||
this.geometryFunction = options.geometryFunction || function(feature) {
|
||||
const geometry = /** @type {module:ol/geom/Point} */ (feature.getGeometry());
|
||||
assert(geometry instanceof Point,
|
||||
10); // The default `geometryFunction` can only handle `module:ol/geom/Point~Point` geometries
|
||||
return geometry;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {module:ol/source/Vector}
|
||||
* @protected
|
||||
*/
|
||||
this.source = options.source;
|
||||
|
||||
listen(this.source, EventType.CHANGE, this.refresh, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @protected
|
||||
* Get the distance in pixels between clusters.
|
||||
* @return {number} Distance.
|
||||
* @api
|
||||
*/
|
||||
this.resolution = undefined;
|
||||
getDistance() {
|
||||
return this.distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @protected
|
||||
* Get a reference to the wrapped source.
|
||||
* @return {module:ol/source/Vector} Source.
|
||||
* @api
|
||||
*/
|
||||
this.distance = options.distance !== undefined ? options.distance : 20;
|
||||
getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Array.<module:ol/Feature>}
|
||||
* @protected
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.features = [];
|
||||
loadFeatures(extent, resolution, projection) {
|
||||
this.source.loadFeatures(extent, resolution, projection);
|
||||
if (resolution !== this.resolution) {
|
||||
this.clear();
|
||||
this.resolution = resolution;
|
||||
this.cluster();
|
||||
this.addFeatures(this.features);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/Feature} feature Feature.
|
||||
* @return {module:ol/geom/Point} Cluster calculation point.
|
||||
* @protected
|
||||
* Set the distance in pixels between clusters.
|
||||
* @param {number} distance The distance in pixels.
|
||||
* @api
|
||||
*/
|
||||
this.geometryFunction = options.geometryFunction || function(feature) {
|
||||
const geometry = /** @type {module:ol/geom/Point} */ (feature.getGeometry());
|
||||
assert(geometry instanceof Point,
|
||||
10); // The default `geometryFunction` can only handle `module:ol/geom/Point~Point` geometries
|
||||
return geometry;
|
||||
};
|
||||
setDistance(distance) {
|
||||
this.distance = distance;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the source changing
|
||||
* @override
|
||||
*/
|
||||
refresh() {
|
||||
this.clear();
|
||||
this.cluster();
|
||||
this.addFeatures(this.features);
|
||||
VectorSource.prototype.refresh.call(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module:ol/source/Vector}
|
||||
* @protected
|
||||
*/
|
||||
this.source = options.source;
|
||||
cluster() {
|
||||
if (this.resolution === undefined) {
|
||||
return;
|
||||
}
|
||||
this.features.length = 0;
|
||||
const extent = createEmpty();
|
||||
const mapDistance = this.distance * this.resolution;
|
||||
const features = this.source.getFeatures();
|
||||
|
||||
listen(this.source, EventType.CHANGE, this.refresh, this);
|
||||
};
|
||||
/**
|
||||
* @type {!Object.<string, boolean>}
|
||||
*/
|
||||
const clustered = {};
|
||||
|
||||
for (let i = 0, ii = features.length; i < ii; i++) {
|
||||
const feature = features[i];
|
||||
if (!(getUid(feature).toString() in clustered)) {
|
||||
const geometry = this.geometryFunction(feature);
|
||||
if (geometry) {
|
||||
const coordinates = geometry.getCoordinates();
|
||||
createOrUpdateFromCoordinate(coordinates, extent);
|
||||
buffer(extent, mapDistance, extent);
|
||||
|
||||
let neighbors = this.source.getFeaturesInExtent(extent);
|
||||
neighbors = neighbors.filter(function(neighbor) {
|
||||
const uid = getUid(neighbor).toString();
|
||||
if (!(uid in clustered)) {
|
||||
clustered[uid] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.features.push(this.createCluster(neighbors));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array.<module:ol/Feature>} features Features
|
||||
* @return {module:ol/Feature} The cluster feature.
|
||||
* @protected
|
||||
*/
|
||||
createCluster(features) {
|
||||
const centroid = [0, 0];
|
||||
for (let i = features.length - 1; i >= 0; --i) {
|
||||
const geometry = this.geometryFunction(features[i]);
|
||||
if (geometry) {
|
||||
addCoordinate(centroid, geometry.getCoordinates());
|
||||
} else {
|
||||
features.splice(i, 1);
|
||||
}
|
||||
}
|
||||
scaleCoordinate(centroid, 1 / features.length);
|
||||
|
||||
const cluster = new Feature(new Point(centroid));
|
||||
cluster.set('features', features);
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Cluster, VectorSource);
|
||||
|
||||
|
||||
/**
|
||||
* Get the distance in pixels between clusters.
|
||||
* @return {number} Distance.
|
||||
* @api
|
||||
*/
|
||||
Cluster.prototype.getDistance = function() {
|
||||
return this.distance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a reference to the wrapped source.
|
||||
* @return {module:ol/source/Vector} Source.
|
||||
* @api
|
||||
*/
|
||||
Cluster.prototype.getSource = function() {
|
||||
return this.source;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Cluster.prototype.loadFeatures = function(extent, resolution, projection) {
|
||||
this.source.loadFeatures(extent, resolution, projection);
|
||||
if (resolution !== this.resolution) {
|
||||
this.clear();
|
||||
this.resolution = resolution;
|
||||
this.cluster();
|
||||
this.addFeatures(this.features);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the distance in pixels between clusters.
|
||||
* @param {number} distance The distance in pixels.
|
||||
* @api
|
||||
*/
|
||||
Cluster.prototype.setDistance = function(distance) {
|
||||
this.distance = distance;
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* handle the source changing
|
||||
* @override
|
||||
*/
|
||||
Cluster.prototype.refresh = function() {
|
||||
this.clear();
|
||||
this.cluster();
|
||||
this.addFeatures(this.features);
|
||||
VectorSource.prototype.refresh.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
Cluster.prototype.cluster = function() {
|
||||
if (this.resolution === undefined) {
|
||||
return;
|
||||
}
|
||||
this.features.length = 0;
|
||||
const extent = createEmpty();
|
||||
const mapDistance = this.distance * this.resolution;
|
||||
const features = this.source.getFeatures();
|
||||
|
||||
/**
|
||||
* @type {!Object.<string, boolean>}
|
||||
*/
|
||||
const clustered = {};
|
||||
|
||||
for (let i = 0, ii = features.length; i < ii; i++) {
|
||||
const feature = features[i];
|
||||
if (!(getUid(feature).toString() in clustered)) {
|
||||
const geometry = this.geometryFunction(feature);
|
||||
if (geometry) {
|
||||
const coordinates = geometry.getCoordinates();
|
||||
createOrUpdateFromCoordinate(coordinates, extent);
|
||||
buffer(extent, mapDistance, extent);
|
||||
|
||||
let neighbors = this.source.getFeaturesInExtent(extent);
|
||||
neighbors = neighbors.filter(function(neighbor) {
|
||||
const uid = getUid(neighbor).toString();
|
||||
if (!(uid in clustered)) {
|
||||
clustered[uid] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.features.push(this.createCluster(neighbors));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<module:ol/Feature>} features Features
|
||||
* @return {module:ol/Feature} The cluster feature.
|
||||
* @protected
|
||||
*/
|
||||
Cluster.prototype.createCluster = function(features) {
|
||||
const centroid = [0, 0];
|
||||
for (let i = features.length - 1; i >= 0; --i) {
|
||||
const geometry = this.geometryFunction(features[i]);
|
||||
if (geometry) {
|
||||
addCoordinate(centroid, geometry.getCoordinates());
|
||||
} else {
|
||||
features.splice(i, 1);
|
||||
}
|
||||
}
|
||||
scaleCoordinate(centroid, 1 / features.length);
|
||||
|
||||
const cluster = new Feature(new Point(centroid));
|
||||
cluster.set('features', features);
|
||||
return cluster;
|
||||
};
|
||||
export default Cluster;
|
||||
|
||||
@@ -88,146 +88,143 @@ inherits(ImageSourceEvent, Event);
|
||||
* @param {module:ol/source/Image~Options} options Single image source options.
|
||||
* @api
|
||||
*/
|
||||
const ImageSource = function(options) {
|
||||
Source.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
state: options.state
|
||||
});
|
||||
class ImageSource {
|
||||
constructor(options) {
|
||||
Source.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
state: options.state
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.resolutions_ = options.resolutions !== undefined ?
|
||||
options.resolutions : null;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/reproj/Image}
|
||||
*/
|
||||
this.reprojectedImage_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.reprojectedRevision_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
* @return {Array.<number>} Resolutions.
|
||||
* @override
|
||||
*/
|
||||
this.resolutions_ = options.resolutions !== undefined ?
|
||||
options.resolutions : null;
|
||||
|
||||
getResolutions() {
|
||||
return this.resolutions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/reproj/Image}
|
||||
* @protected
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {number} Resolution.
|
||||
*/
|
||||
this.reprojectedImage_ = null;
|
||||
|
||||
findNearestResolution(resolution) {
|
||||
if (this.resolutions_) {
|
||||
const idx = linearFindNearest(this.resolutions_, resolution, 0);
|
||||
resolution = this.resolutions_[idx];
|
||||
}
|
||||
return resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/ImageBase} Single image.
|
||||
*/
|
||||
this.reprojectedRevision_ = 0;
|
||||
};
|
||||
getImage(extent, resolution, pixelRatio, projection) {
|
||||
const sourceProjection = this.getProjection();
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
!sourceProjection ||
|
||||
!projection ||
|
||||
equivalent(sourceProjection, projection)) {
|
||||
if (sourceProjection) {
|
||||
projection = sourceProjection;
|
||||
}
|
||||
return this.getImageInternal(extent, resolution, pixelRatio, projection);
|
||||
} else {
|
||||
if (this.reprojectedImage_) {
|
||||
if (this.reprojectedRevision_ == this.getRevision() &&
|
||||
equivalent(
|
||||
this.reprojectedImage_.getProjection(), projection) &&
|
||||
this.reprojectedImage_.getResolution() == resolution &&
|
||||
equals(this.reprojectedImage_.getExtent(), extent)) {
|
||||
return this.reprojectedImage_;
|
||||
}
|
||||
this.reprojectedImage_.dispose();
|
||||
this.reprojectedImage_ = null;
|
||||
}
|
||||
|
||||
this.reprojectedImage_ = new ReprojImage(
|
||||
sourceProjection, projection, extent, resolution, pixelRatio,
|
||||
function(extent, resolution, pixelRatio) {
|
||||
return this.getImageInternal(extent, resolution,
|
||||
pixelRatio, sourceProjection);
|
||||
}.bind(this));
|
||||
this.reprojectedRevision_ = this.getRevision();
|
||||
|
||||
return this.reprojectedImage_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/ImageBase} Single image.
|
||||
* @protected
|
||||
*/
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {}
|
||||
|
||||
/**
|
||||
* Handle image change events.
|
||||
* @param {module:ol/events/Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
handleImageChange(event) {
|
||||
const image = /** @type {module:ol/Image} */ (event.target);
|
||||
switch (image.getState()) {
|
||||
case ImageState.LOADING:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADSTART,
|
||||
image));
|
||||
break;
|
||||
case ImageState.LOADED:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADEND,
|
||||
image));
|
||||
break;
|
||||
case ImageState.ERROR:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADERROR,
|
||||
image));
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ImageSource, Source);
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Resolutions.
|
||||
* @override
|
||||
*/
|
||||
ImageSource.prototype.getResolutions = function() {
|
||||
return this.resolutions_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {number} Resolution.
|
||||
*/
|
||||
ImageSource.prototype.findNearestResolution = function(resolution) {
|
||||
if (this.resolutions_) {
|
||||
const idx = linearFindNearest(this.resolutions_, resolution, 0);
|
||||
resolution = this.resolutions_[idx];
|
||||
}
|
||||
return resolution;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/ImageBase} Single image.
|
||||
*/
|
||||
ImageSource.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
|
||||
const sourceProjection = this.getProjection();
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
!sourceProjection ||
|
||||
!projection ||
|
||||
equivalent(sourceProjection, projection)) {
|
||||
if (sourceProjection) {
|
||||
projection = sourceProjection;
|
||||
}
|
||||
return this.getImageInternal(extent, resolution, pixelRatio, projection);
|
||||
} else {
|
||||
if (this.reprojectedImage_) {
|
||||
if (this.reprojectedRevision_ == this.getRevision() &&
|
||||
equivalent(
|
||||
this.reprojectedImage_.getProjection(), projection) &&
|
||||
this.reprojectedImage_.getResolution() == resolution &&
|
||||
equals(this.reprojectedImage_.getExtent(), extent)) {
|
||||
return this.reprojectedImage_;
|
||||
}
|
||||
this.reprojectedImage_.dispose();
|
||||
this.reprojectedImage_ = null;
|
||||
}
|
||||
|
||||
this.reprojectedImage_ = new ReprojImage(
|
||||
sourceProjection, projection, extent, resolution, pixelRatio,
|
||||
function(extent, resolution, pixelRatio) {
|
||||
return this.getImageInternal(extent, resolution,
|
||||
pixelRatio, sourceProjection);
|
||||
}.bind(this));
|
||||
this.reprojectedRevision_ = this.getRevision();
|
||||
|
||||
return this.reprojectedImage_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/ImageBase} Single image.
|
||||
* @protected
|
||||
*/
|
||||
ImageSource.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {};
|
||||
|
||||
|
||||
/**
|
||||
* Handle image change events.
|
||||
* @param {module:ol/events/Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
ImageSource.prototype.handleImageChange = function(event) {
|
||||
const image = /** @type {module:ol/Image} */ (event.target);
|
||||
switch (image.getState()) {
|
||||
case ImageState.LOADING:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADSTART,
|
||||
image));
|
||||
break;
|
||||
case ImageState.LOADED:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADEND,
|
||||
image));
|
||||
break;
|
||||
case ImageState.ERROR:
|
||||
this.dispatchEvent(
|
||||
new ImageSourceEvent(ImageSourceEventType.IMAGELOADERROR,
|
||||
image));
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default image load function for image sources that use module:ol/Image~Image image
|
||||
* instances.
|
||||
|
||||
@@ -54,246 +54,242 @@ import {appendParams} from '../uri.js';
|
||||
* @param {module:ol/source/ImageArcGISRest~Options=} opt_options Image ArcGIS Rest Options.
|
||||
* @api
|
||||
*/
|
||||
const ImageArcGISRest = function(opt_options) {
|
||||
class ImageArcGISRest {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options || {};
|
||||
const options = opt_options || {};
|
||||
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.imageSize_ = [0, 0];
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
getParams() {
|
||||
return this.params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {
|
||||
|
||||
if (this.url_ === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
pixelRatio = this.hidpi_ ? pixelRatio : 1;
|
||||
|
||||
const image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), extent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
const params = {
|
||||
'F': 'image',
|
||||
'FORMAT': 'PNG32',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(params, this.params_);
|
||||
|
||||
extent = extent.slice();
|
||||
const centerX = (extent[0] + extent[2]) / 2;
|
||||
const centerY = (extent[1] + extent[3]) / 2;
|
||||
if (this.ratio_ != 1) {
|
||||
const halfWidth = this.ratio_ * getWidth(extent) / 2;
|
||||
const halfHeight = this.ratio_ * getHeight(extent) / 2;
|
||||
extent[0] = centerX - halfWidth;
|
||||
extent[1] = centerY - halfHeight;
|
||||
extent[2] = centerX + halfWidth;
|
||||
extent[3] = centerY + halfHeight;
|
||||
}
|
||||
|
||||
const imageResolution = resolution / pixelRatio;
|
||||
|
||||
// Compute an integer width and height.
|
||||
const width = Math.ceil(getWidth(extent) / imageResolution);
|
||||
const height = Math.ceil(getHeight(extent) / imageResolution);
|
||||
|
||||
// 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;
|
||||
|
||||
this.imageSize_[0] = width;
|
||||
this.imageSize_[1] = height;
|
||||
|
||||
const url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
|
||||
projection, params);
|
||||
|
||||
this.image_ = new ImageWrapper(extent, resolution, pixelRatio,
|
||||
url, this.crossOrigin_, this.imageLoadFunction_);
|
||||
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
return this.image_;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
getImageLoadFunction() {
|
||||
return this.imageLoadFunction_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string} Request URL.
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
getRequestUrl_(extent, size, pixelRatio, projection, params) {
|
||||
// ArcGIS Server only wants the numeric portion of the projection ID.
|
||||
const srid = projection.getCode().split(':').pop();
|
||||
|
||||
params['SIZE'] = size[0] + ',' + size[1];
|
||||
params['BBOX'] = extent.join(',');
|
||||
params['BBOXSR'] = srid;
|
||||
params['IMAGESR'] = srid;
|
||||
params['DPI'] = Math.round(90 * pixelRatio);
|
||||
|
||||
const url = this.url_;
|
||||
|
||||
const modifiedUrl = url
|
||||
.replace(/MapServer\/?$/, 'MapServer/export')
|
||||
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
|
||||
if (modifiedUrl == url) {
|
||||
assert(false, 50); // `options.featureTypes` should be an Array
|
||||
}
|
||||
return appendParams(modifiedUrl, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
* Return the URL used for this ArcGIS source.
|
||||
* @return {string|undefined} URL.
|
||||
* @api
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
getUrl() {
|
||||
return this.url_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
* Set the image load function of the source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
this.image_ = null;
|
||||
setImageLoadFunction(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
* Set the URL to use for requests.
|
||||
* @param {string|undefined} url URL.
|
||||
* @api
|
||||
*/
|
||||
this.imageSize_ = [0, 0];
|
||||
|
||||
setUrl(url) {
|
||||
if (url != this.url_) {
|
||||
this.url_ = url;
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
|
||||
|
||||
};
|
||||
updateParams(params) {
|
||||
assign(this.params_, params);
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ImageArcGISRest, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.getParams = function() {
|
||||
return this.params_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ImageArcGISRest.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
|
||||
|
||||
if (this.url_ === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
pixelRatio = this.hidpi_ ? pixelRatio : 1;
|
||||
|
||||
const image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), extent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
const params = {
|
||||
'F': 'image',
|
||||
'FORMAT': 'PNG32',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(params, this.params_);
|
||||
|
||||
extent = extent.slice();
|
||||
const centerX = (extent[0] + extent[2]) / 2;
|
||||
const centerY = (extent[1] + extent[3]) / 2;
|
||||
if (this.ratio_ != 1) {
|
||||
const halfWidth = this.ratio_ * getWidth(extent) / 2;
|
||||
const halfHeight = this.ratio_ * getHeight(extent) / 2;
|
||||
extent[0] = centerX - halfWidth;
|
||||
extent[1] = centerY - halfHeight;
|
||||
extent[2] = centerX + halfWidth;
|
||||
extent[3] = centerY + halfHeight;
|
||||
}
|
||||
|
||||
const imageResolution = resolution / pixelRatio;
|
||||
|
||||
// Compute an integer width and height.
|
||||
const width = Math.ceil(getWidth(extent) / imageResolution);
|
||||
const height = Math.ceil(getHeight(extent) / imageResolution);
|
||||
|
||||
// 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;
|
||||
|
||||
this.imageSize_[0] = width;
|
||||
this.imageSize_[1] = height;
|
||||
|
||||
const url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
|
||||
projection, params);
|
||||
|
||||
this.image_ = new ImageWrapper(extent, resolution, pixelRatio,
|
||||
url, this.crossOrigin_, this.imageLoadFunction_);
|
||||
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
return this.image_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.getImageLoadFunction = function() {
|
||||
return this.imageLoadFunction_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string} Request URL.
|
||||
* @private
|
||||
*/
|
||||
ImageArcGISRest.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
|
||||
// ArcGIS Server only wants the numeric portion of the projection ID.
|
||||
const srid = projection.getCode().split(':').pop();
|
||||
|
||||
params['SIZE'] = size[0] + ',' + size[1];
|
||||
params['BBOX'] = extent.join(',');
|
||||
params['BBOXSR'] = srid;
|
||||
params['IMAGESR'] = srid;
|
||||
params['DPI'] = Math.round(90 * pixelRatio);
|
||||
|
||||
const url = this.url_;
|
||||
|
||||
const modifiedUrl = url
|
||||
.replace(/MapServer\/?$/, 'MapServer/export')
|
||||
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
|
||||
if (modifiedUrl == url) {
|
||||
assert(false, 50); // `options.featureTypes` should be an Array
|
||||
}
|
||||
return appendParams(modifiedUrl, params);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the URL used for this ArcGIS source.
|
||||
* @return {string|undefined} URL.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.getUrl = function() {
|
||||
return this.url_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the image load function of the source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.setImageLoadFunction = function(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the URL to use for requests.
|
||||
* @param {string|undefined} url URL.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.setUrl = function(url) {
|
||||
if (url != this.url_) {
|
||||
this.url_ = url;
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
ImageArcGISRest.prototype.updateParams = function(params) {
|
||||
assign(this.params_, params);
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
};
|
||||
export default ImageArcGISRest;
|
||||
|
||||
@@ -51,74 +51,77 @@ import ImageSource from '../source/Image.js';
|
||||
* @param {module:ol/source/ImageCanvas~Options=} options ImageCanvas options.
|
||||
* @api
|
||||
*/
|
||||
const ImageCanvasSource = function(options) {
|
||||
class ImageCanvasSource {
|
||||
constructor(options) {
|
||||
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions,
|
||||
state: options.state
|
||||
});
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions,
|
||||
state: options.state
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/ImageCanvas~FunctionType}
|
||||
*/
|
||||
this.canvasFunction_ = options.canvasFunction;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/ImageCanvas~FunctionType}
|
||||
*/
|
||||
this.canvasFunction_ = options.canvasFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/ImageCanvas}
|
||||
*/
|
||||
this.canvas_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/ImageCanvas}
|
||||
*/
|
||||
this.canvas_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ?
|
||||
options.ratio : 1.5;
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ?
|
||||
options.ratio : 1.5;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
|
||||
let canvas = this.canvas_;
|
||||
if (canvas &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
canvas.getResolution() == resolution &&
|
||||
canvas.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(canvas.getExtent(), extent)) {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
extent = extent.slice();
|
||||
scaleFromCenter(extent, this.ratio_);
|
||||
const width = getWidth(extent) / resolution;
|
||||
const height = getHeight(extent) / resolution;
|
||||
const size = [width * pixelRatio, height * pixelRatio];
|
||||
|
||||
const canvasElement = this.canvasFunction_(
|
||||
extent, resolution, pixelRatio, size, projection);
|
||||
if (canvasElement) {
|
||||
canvas = new ImageCanvas(extent, resolution, pixelRatio, canvasElement);
|
||||
}
|
||||
this.canvas_ = canvas;
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ImageCanvasSource, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ImageCanvasSource.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
|
||||
let canvas = this.canvas_;
|
||||
if (canvas &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
canvas.getResolution() == resolution &&
|
||||
canvas.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(canvas.getExtent(), extent)) {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
extent = extent.slice();
|
||||
scaleFromCenter(extent, this.ratio_);
|
||||
const width = getWidth(extent) / resolution;
|
||||
const height = getHeight(extent) / resolution;
|
||||
const size = [width * pixelRatio, height * pixelRatio];
|
||||
|
||||
const canvasElement = this.canvasFunction_(
|
||||
extent, resolution, pixelRatio, size, projection);
|
||||
if (canvasElement) {
|
||||
canvas = new ImageCanvas(extent, resolution, pixelRatio, canvasElement);
|
||||
}
|
||||
this.canvas_ = canvas;
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
return canvas;
|
||||
};
|
||||
export default ImageCanvasSource;
|
||||
|
||||
@@ -42,150 +42,199 @@ import {appendParams} from '../uri.js';
|
||||
* @param {module:ol/source/ImageMapGuide~Options=} options ImageMapGuide options.
|
||||
* @api
|
||||
*/
|
||||
const ImageMapGuide = function(options) {
|
||||
class ImageMapGuide {
|
||||
constructor(options) {
|
||||
|
||||
ImageSource.call(this, {
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
ImageSource.call(this, {
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.displayDpi_ = options.displayDpi !== undefined ?
|
||||
options.displayDpi : 96;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.metersPerUnit_ = options.metersPerUnit !== undefined ?
|
||||
options.metersPerUnit : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.useOverlay_ = options.useOverlay !== undefined ?
|
||||
options.useOverlay : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
getParams() {
|
||||
return this.params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.displayDpi_ = options.displayDpi !== undefined ?
|
||||
options.displayDpi : 96;
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
pixelRatio = this.hidpi_ ? pixelRatio : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
let image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), extent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
if (this.ratio_ != 1) {
|
||||
extent = extent.slice();
|
||||
scaleFromCenter(extent, this.ratio_);
|
||||
}
|
||||
const width = getWidth(extent) / resolution;
|
||||
const height = getHeight(extent) / resolution;
|
||||
const size = [width * pixelRatio, height * pixelRatio];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
if (this.url_ !== undefined) {
|
||||
const imageUrl = this.getUrl(this.url_, this.params_, extent, size,
|
||||
projection);
|
||||
image = new ImageWrapper(extent, resolution, pixelRatio,
|
||||
imageUrl, this.crossOrigin_,
|
||||
this.imageLoadFunction_);
|
||||
listen(image, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
} else {
|
||||
image = null;
|
||||
}
|
||||
this.image_ = image;
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.metersPerUnit_ = options.metersPerUnit !== undefined ?
|
||||
options.metersPerUnit : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.useOverlay_ = options.useOverlay !== undefined ?
|
||||
options.useOverlay : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
};
|
||||
|
||||
inherits(ImageMapGuide, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
ImageMapGuide.prototype.getParams = function() {
|
||||
return this.params_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ImageMapGuide.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
pixelRatio = this.hidpi_ ? pixelRatio : 1;
|
||||
|
||||
let image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), extent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
if (this.ratio_ != 1) {
|
||||
extent = extent.slice();
|
||||
scaleFromCenter(extent, this.ratio_);
|
||||
/**
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
getImageLoadFunction() {
|
||||
return this.imageLoadFunction_;
|
||||
}
|
||||
const width = getWidth(extent) / resolution;
|
||||
const height = getHeight(extent) / resolution;
|
||||
const size = [width * pixelRatio, height * pixelRatio];
|
||||
|
||||
if (this.url_ !== undefined) {
|
||||
const imageUrl = this.getUrl(this.url_, this.params_, extent, size,
|
||||
projection);
|
||||
image = new ImageWrapper(extent, resolution, pixelRatio,
|
||||
imageUrl, this.crossOrigin_,
|
||||
this.imageLoadFunction_);
|
||||
listen(image, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
} else {
|
||||
image = null;
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
updateParams(params) {
|
||||
assign(this.params_, params);
|
||||
this.changed();
|
||||
}
|
||||
this.image_ = image;
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
return image;
|
||||
};
|
||||
/**
|
||||
* @param {string} baseUrl The mapagent url.
|
||||
* @param {Object.<string, string|number>} params Request parameters.
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {string} The mapagent map image request URL.
|
||||
*/
|
||||
getUrl(baseUrl, params, extent, size, projection) {
|
||||
const scale = getScale(extent, size,
|
||||
this.metersPerUnit_, this.displayDpi_);
|
||||
const center = getCenter(extent);
|
||||
const baseParams = {
|
||||
'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE',
|
||||
'VERSION': '2.0.0',
|
||||
'LOCALE': 'en',
|
||||
'CLIENTAGENT': 'ol/source/ImageMapGuide source',
|
||||
'CLIP': '1',
|
||||
'SETDISPLAYDPI': this.displayDpi_,
|
||||
'SETDISPLAYWIDTH': Math.round(size[0]),
|
||||
'SETDISPLAYHEIGHT': Math.round(size[1]),
|
||||
'SETVIEWSCALE': scale,
|
||||
'SETVIEWCENTERX': center[0],
|
||||
'SETVIEWCENTERY': center[1]
|
||||
};
|
||||
assign(baseParams, params);
|
||||
return appendParams(baseUrl, baseParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image load function of the MapGuide source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
setImageLoadFunction(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageMapGuide.prototype.getImageLoadFunction = function() {
|
||||
return this.imageLoadFunction_;
|
||||
};
|
||||
inherits(ImageMapGuide, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
@@ -209,55 +258,4 @@ function getScale(extent, size, metersPerUnit, dpi) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
ImageMapGuide.prototype.updateParams = function(params) {
|
||||
assign(this.params_, params);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} baseUrl The mapagent url.
|
||||
* @param {Object.<string, string|number>} params Request parameters.
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {string} The mapagent map image request URL.
|
||||
*/
|
||||
ImageMapGuide.prototype.getUrl = function(baseUrl, params, extent, size, projection) {
|
||||
const scale = getScale(extent, size,
|
||||
this.metersPerUnit_, this.displayDpi_);
|
||||
const center = getCenter(extent);
|
||||
const baseParams = {
|
||||
'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE',
|
||||
'VERSION': '2.0.0',
|
||||
'LOCALE': 'en',
|
||||
'CLIENTAGENT': 'ol/source/ImageMapGuide source',
|
||||
'CLIP': '1',
|
||||
'SETDISPLAYDPI': this.displayDpi_,
|
||||
'SETDISPLAYWIDTH': Math.round(size[0]),
|
||||
'SETDISPLAYHEIGHT': Math.round(size[1]),
|
||||
'SETVIEWSCALE': scale,
|
||||
'SETVIEWCENTERX': center[0],
|
||||
'SETVIEWCENTERY': center[1]
|
||||
};
|
||||
assign(baseParams, params);
|
||||
return appendParams(baseUrl, baseParams);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the image load function of the MapGuide source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageMapGuide.prototype.setImageLoadFunction = function(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
};
|
||||
export default ImageMapGuide;
|
||||
|
||||
@@ -37,77 +37,79 @@ import ImageSource, {defaultImageLoadFunction} from '../source/Image.js';
|
||||
* @param {module:ol/source/ImageStatic~Options=} options ImageStatic options.
|
||||
* @api
|
||||
*/
|
||||
const Static = function(options) {
|
||||
const imageExtent = options.imageExtent;
|
||||
class Static {
|
||||
constructor(options) {
|
||||
const imageExtent = options.imageExtent;
|
||||
|
||||
const crossOrigin = options.crossOrigin !== undefined ?
|
||||
options.crossOrigin : null;
|
||||
const crossOrigin = options.crossOrigin !== undefined ?
|
||||
options.crossOrigin : null;
|
||||
|
||||
const /** @type {module:ol/Image~LoadFunction} */ imageLoadFunction =
|
||||
options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
const /** @type {module:ol/Image~LoadFunction} */ imageLoadFunction =
|
||||
options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: getProjection(options.projection)
|
||||
});
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: getProjection(options.projection)
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = new ImageWrapper(imageExtent, undefined, 1, options.url, crossOrigin, imageLoadFunction);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.imageSize_ = options.imageSize ? options.imageSize : null;
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.image_ = new ImageWrapper(imageExtent, undefined, 1, options.url, crossOrigin, imageLoadFunction);
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {
|
||||
if (intersects(extent, this.image_.getExtent())) {
|
||||
return this.image_;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.imageSize_ = options.imageSize ? options.imageSize : null;
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
};
|
||||
handleImageChange(evt) {
|
||||
if (this.image_.getState() == ImageState.LOADED) {
|
||||
const imageExtent = this.image_.getExtent();
|
||||
const image = this.image_.getImage();
|
||||
let imageWidth, imageHeight;
|
||||
if (this.imageSize_) {
|
||||
imageWidth = this.imageSize_[0];
|
||||
imageHeight = this.imageSize_[1];
|
||||
} else {
|
||||
imageWidth = image.width;
|
||||
imageHeight = image.height;
|
||||
}
|
||||
const resolution = getHeight(imageExtent) / imageHeight;
|
||||
const targetWidth = Math.ceil(getWidth(imageExtent) / resolution);
|
||||
if (targetWidth != imageWidth) {
|
||||
const context = createCanvasContext2D(targetWidth, imageHeight);
|
||||
const canvas = context.canvas;
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight,
|
||||
0, 0, canvas.width, canvas.height);
|
||||
this.image_.setImage(canvas);
|
||||
}
|
||||
}
|
||||
ImageSource.prototype.handleImageChange.call(this, evt);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Static, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Static.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
|
||||
if (intersects(extent, this.image_.getExtent())) {
|
||||
return this.image_;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Static.prototype.handleImageChange = function(evt) {
|
||||
if (this.image_.getState() == ImageState.LOADED) {
|
||||
const imageExtent = this.image_.getExtent();
|
||||
const image = this.image_.getImage();
|
||||
let imageWidth, imageHeight;
|
||||
if (this.imageSize_) {
|
||||
imageWidth = this.imageSize_[0];
|
||||
imageHeight = this.imageSize_[1];
|
||||
} else {
|
||||
imageWidth = image.width;
|
||||
imageHeight = image.height;
|
||||
}
|
||||
const resolution = getHeight(imageExtent) / imageHeight;
|
||||
const targetWidth = Math.ceil(getWidth(imageExtent) / resolution);
|
||||
if (targetWidth != imageWidth) {
|
||||
const context = createCanvasContext2D(targetWidth, imageHeight);
|
||||
const canvas = context.canvas;
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight,
|
||||
0, 0, canvas.width, canvas.height);
|
||||
this.image_.setImage(canvas);
|
||||
}
|
||||
}
|
||||
ImageSource.prototype.handleImageChange.call(this, evt);
|
||||
};
|
||||
export default Static;
|
||||
|
||||
@@ -53,86 +53,329 @@ import {appendParams} from '../uri.js';
|
||||
* @param {module:ol/source/ImageWMS~Options=} [opt_options] ImageWMS options.
|
||||
* @api
|
||||
*/
|
||||
const ImageWMS = function(opt_options) {
|
||||
class ImageWMS {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options || {};
|
||||
const options = opt_options || {};
|
||||
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
ImageSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
projection: options.projection,
|
||||
resolutions: options.resolutions
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.v13_ = true;
|
||||
this.updateV13_();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/WMSServerType|undefined}
|
||||
*/
|
||||
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.imageSize_ = [0, 0];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
|
||||
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
|
||||
* constructed.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
|
||||
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
|
||||
* in the `LAYERS` parameter will be used. `VERSION` should not be
|
||||
* specified here.
|
||||
* @return {string|undefined} GetFeatureInfo URL.
|
||||
* @api
|
||||
*/
|
||||
getGetFeatureInfoUrl(coordinate, resolution, projection, params) {
|
||||
if (this.url_ === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const projectionObj = getProjection(projection);
|
||||
const sourceProjectionObj = this.getProjection();
|
||||
|
||||
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
|
||||
resolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, resolution);
|
||||
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
|
||||
}
|
||||
|
||||
const extent = getForViewAndSize(coordinate, resolution, 0,
|
||||
GETFEATUREINFO_IMAGE_SIZE);
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetFeatureInfo',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true,
|
||||
'QUERY_LAYERS': this.params_['LAYERS']
|
||||
};
|
||||
assign(baseParams, this.params_, params);
|
||||
|
||||
const x = Math.floor((coordinate[0] - extent[0]) / resolution);
|
||||
const y = Math.floor((extent[3] - coordinate[1]) / resolution);
|
||||
baseParams[this.v13_ ? 'I' : 'X'] = x;
|
||||
baseParams[this.v13_ ? 'J' : 'Y'] = y;
|
||||
|
||||
return this.getRequestUrl_(
|
||||
extent, GETFEATUREINFO_IMAGE_SIZE,
|
||||
1, sourceProjectionObj || projectionObj, baseParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
getParams() {
|
||||
return this.params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getImageInternal(extent, resolution, pixelRatio, projection) {
|
||||
|
||||
if (this.url_ === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
|
||||
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
|
||||
pixelRatio = 1;
|
||||
}
|
||||
|
||||
const imageResolution = resolution / pixelRatio;
|
||||
|
||||
const center = getCenter(extent);
|
||||
const viewWidth = Math.ceil(getWidth(extent) / imageResolution);
|
||||
const viewHeight = Math.ceil(getHeight(extent) / imageResolution);
|
||||
const viewExtent = getForViewAndSize(center, imageResolution, 0,
|
||||
[viewWidth, viewHeight]);
|
||||
const requestWidth = Math.ceil(this.ratio_ * getWidth(extent) / imageResolution);
|
||||
const requestHeight = Math.ceil(this.ratio_ * getHeight(extent) / imageResolution);
|
||||
const requestExtent = getForViewAndSize(center, imageResolution, 0,
|
||||
[requestWidth, requestHeight]);
|
||||
|
||||
const image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), viewExtent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
const params = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetMap',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(params, this.params_);
|
||||
|
||||
this.imageSize_[0] = Math.round(getWidth(requestExtent) / imageResolution);
|
||||
this.imageSize_[1] = Math.round(getHeight(requestExtent) / imageResolution);
|
||||
|
||||
const url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
|
||||
projection, params);
|
||||
|
||||
this.image_ = new ImageWrapper(requestExtent, resolution, pixelRatio,
|
||||
url, this.crossOrigin_, this.imageLoadFunction_);
|
||||
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
return this.image_;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
getImageLoadFunction() {
|
||||
return this.imageLoadFunction_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string} Request URL.
|
||||
* @private
|
||||
*/
|
||||
getRequestUrl_(extent, size, pixelRatio, projection, params) {
|
||||
|
||||
assert(this.url_ !== undefined, 9); // `url` must be configured or set using `#setUrl()`
|
||||
|
||||
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
|
||||
|
||||
if (!('STYLES' in this.params_)) {
|
||||
params['STYLES'] = '';
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
switch (this.serverType_) {
|
||||
case WMSServerType.GEOSERVER:
|
||||
const dpi = (90 * pixelRatio + 0.5) | 0;
|
||||
if ('FORMAT_OPTIONS' in params) {
|
||||
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
|
||||
} else {
|
||||
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
|
||||
}
|
||||
break;
|
||||
case WMSServerType.MAPSERVER:
|
||||
params['MAP_RESOLUTION'] = 90 * pixelRatio;
|
||||
break;
|
||||
case WMSServerType.CARMENTA_SERVER:
|
||||
case WMSServerType.QGIS:
|
||||
params['DPI'] = 90 * pixelRatio;
|
||||
break;
|
||||
default:
|
||||
assert(false, 8); // Unknown `serverType` configured
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
params['WIDTH'] = size[0];
|
||||
params['HEIGHT'] = size[1];
|
||||
|
||||
const axisOrientation = projection.getAxisOrientation();
|
||||
let bbox;
|
||||
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
|
||||
bbox = [extent[1], extent[0], extent[3], extent[2]];
|
||||
} else {
|
||||
bbox = extent;
|
||||
}
|
||||
params['BBOX'] = bbox.join(',');
|
||||
|
||||
return appendParams(/** @type {string} */ (this.url_), params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL used for this WMS source.
|
||||
* @return {string|undefined} URL.
|
||||
* @api
|
||||
*/
|
||||
getUrl() {
|
||||
return this.url_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image load function of the source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
setImageLoadFunction(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL to use for requests.
|
||||
* @param {string|undefined} url URL.
|
||||
* @api
|
||||
*/
|
||||
setUrl(url) {
|
||||
if (url != this.url_) {
|
||||
this.url_ = url;
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
updateParams(params) {
|
||||
assign(this.params_, params);
|
||||
this.updateV13_();
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.url_ = options.url;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image~LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
|
||||
options.imageLoadFunction : defaultImageLoadFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.v13_ = true;
|
||||
this.updateV13_();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/WMSServerType|undefined}
|
||||
*/
|
||||
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/Image}
|
||||
*/
|
||||
this.image_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.imageSize_ = [0, 0];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
|
||||
|
||||
};
|
||||
updateV13_() {
|
||||
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
|
||||
this.v13_ = compareVersions(version, '1.3') >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ImageWMS, ImageSource);
|
||||
|
||||
@@ -144,253 +387,4 @@ inherits(ImageWMS, ImageSource);
|
||||
const GETFEATUREINFO_IMAGE_SIZE = [101, 101];
|
||||
|
||||
|
||||
/**
|
||||
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
|
||||
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
|
||||
* constructed.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
|
||||
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
|
||||
* in the `LAYERS` parameter will be used. `VERSION` should not be
|
||||
* specified here.
|
||||
* @return {string|undefined} GetFeatureInfo URL.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
|
||||
if (this.url_ === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const projectionObj = getProjection(projection);
|
||||
const sourceProjectionObj = this.getProjection();
|
||||
|
||||
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
|
||||
resolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, resolution);
|
||||
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
|
||||
}
|
||||
|
||||
const extent = getForViewAndSize(coordinate, resolution, 0,
|
||||
GETFEATUREINFO_IMAGE_SIZE);
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetFeatureInfo',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true,
|
||||
'QUERY_LAYERS': this.params_['LAYERS']
|
||||
};
|
||||
assign(baseParams, this.params_, params);
|
||||
|
||||
const x = Math.floor((coordinate[0] - extent[0]) / resolution);
|
||||
const y = Math.floor((extent[3] - coordinate[1]) / resolution);
|
||||
baseParams[this.v13_ ? 'I' : 'X'] = x;
|
||||
baseParams[this.v13_ ? 'J' : 'Y'] = y;
|
||||
|
||||
return this.getRequestUrl_(
|
||||
extent, GETFEATUREINFO_IMAGE_SIZE,
|
||||
1, sourceProjectionObj || projectionObj, baseParams);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.getParams = function() {
|
||||
return this.params_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ImageWMS.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
|
||||
|
||||
if (this.url_ === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
resolution = this.findNearestResolution(resolution);
|
||||
|
||||
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
|
||||
pixelRatio = 1;
|
||||
}
|
||||
|
||||
const imageResolution = resolution / pixelRatio;
|
||||
|
||||
const center = getCenter(extent);
|
||||
const viewWidth = Math.ceil(getWidth(extent) / imageResolution);
|
||||
const viewHeight = Math.ceil(getHeight(extent) / imageResolution);
|
||||
const viewExtent = getForViewAndSize(center, imageResolution, 0,
|
||||
[viewWidth, viewHeight]);
|
||||
const requestWidth = Math.ceil(this.ratio_ * getWidth(extent) / imageResolution);
|
||||
const requestHeight = Math.ceil(this.ratio_ * getHeight(extent) / imageResolution);
|
||||
const requestExtent = getForViewAndSize(center, imageResolution, 0,
|
||||
[requestWidth, requestHeight]);
|
||||
|
||||
const image = this.image_;
|
||||
if (image &&
|
||||
this.renderedRevision_ == this.getRevision() &&
|
||||
image.getResolution() == resolution &&
|
||||
image.getPixelRatio() == pixelRatio &&
|
||||
containsExtent(image.getExtent(), viewExtent)) {
|
||||
return image;
|
||||
}
|
||||
|
||||
const params = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetMap',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(params, this.params_);
|
||||
|
||||
this.imageSize_[0] = Math.round(getWidth(requestExtent) / imageResolution);
|
||||
this.imageSize_[1] = Math.round(getHeight(requestExtent) / imageResolution);
|
||||
|
||||
const url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
|
||||
projection, params);
|
||||
|
||||
this.image_ = new ImageWrapper(requestExtent, resolution, pixelRatio,
|
||||
url, this.crossOrigin_, this.imageLoadFunction_);
|
||||
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
listen(this.image_, EventType.CHANGE,
|
||||
this.handleImageChange, this);
|
||||
|
||||
return this.image_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the image load function of the source.
|
||||
* @return {module:ol/Image~LoadFunction} The image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.getImageLoadFunction = function() {
|
||||
return this.imageLoadFunction_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/extent~Extent} extent Extent.
|
||||
* @param {module:ol/size~Size} size Size.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string} Request URL.
|
||||
* @private
|
||||
*/
|
||||
ImageWMS.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
|
||||
|
||||
assert(this.url_ !== undefined, 9); // `url` must be configured or set using `#setUrl()`
|
||||
|
||||
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
|
||||
|
||||
if (!('STYLES' in this.params_)) {
|
||||
params['STYLES'] = '';
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
switch (this.serverType_) {
|
||||
case WMSServerType.GEOSERVER:
|
||||
const dpi = (90 * pixelRatio + 0.5) | 0;
|
||||
if ('FORMAT_OPTIONS' in params) {
|
||||
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
|
||||
} else {
|
||||
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
|
||||
}
|
||||
break;
|
||||
case WMSServerType.MAPSERVER:
|
||||
params['MAP_RESOLUTION'] = 90 * pixelRatio;
|
||||
break;
|
||||
case WMSServerType.CARMENTA_SERVER:
|
||||
case WMSServerType.QGIS:
|
||||
params['DPI'] = 90 * pixelRatio;
|
||||
break;
|
||||
default:
|
||||
assert(false, 8); // Unknown `serverType` configured
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
params['WIDTH'] = size[0];
|
||||
params['HEIGHT'] = size[1];
|
||||
|
||||
const axisOrientation = projection.getAxisOrientation();
|
||||
let bbox;
|
||||
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
|
||||
bbox = [extent[1], extent[0], extent[3], extent[2]];
|
||||
} else {
|
||||
bbox = extent;
|
||||
}
|
||||
params['BBOX'] = bbox.join(',');
|
||||
|
||||
return appendParams(/** @type {string} */ (this.url_), params);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the URL used for this WMS source.
|
||||
* @return {string|undefined} URL.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.getUrl = function() {
|
||||
return this.url_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the image load function of the source.
|
||||
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.setImageLoadFunction = function(imageLoadFunction) {
|
||||
this.image_ = null;
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the URL to use for requests.
|
||||
* @param {string|undefined} url URL.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.setUrl = function(url) {
|
||||
if (url != this.url_) {
|
||||
this.url_ = url;
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
ImageWMS.prototype.updateParams = function(params) {
|
||||
assign(this.params_, params);
|
||||
this.updateV13_();
|
||||
this.image_ = null;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ImageWMS.prototype.updateV13_ = function() {
|
||||
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
|
||||
this.v13_ = compareVersions(version, '1.3') >= 0;
|
||||
};
|
||||
export default ImageWMS;
|
||||
|
||||
@@ -144,276 +144,279 @@ inherits(RasterSourceEvent, Event);
|
||||
* @param {module:ol/source/Raster~Options=} options Options.
|
||||
* @api
|
||||
*/
|
||||
const RasterSource = function(options) {
|
||||
class RasterSource {
|
||||
constructor(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.worker_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.worker_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/Raster~RasterOperationType}
|
||||
*/
|
||||
this.operationType_ = options.operationType !== undefined ?
|
||||
options.operationType : RasterOperationType.PIXEL;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/Raster~RasterOperationType}
|
||||
*/
|
||||
this.operationType_ = options.operationType !== undefined ?
|
||||
options.operationType : RasterOperationType.PIXEL;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.threads_ = options.threads !== undefined ? options.threads : 1;
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.threads_ = options.threads !== undefined ? options.threads : 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<module:ol/renderer/canvas/Layer>}
|
||||
*/
|
||||
this.renderers_ = createRenderers(options.sources);
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<module:ol/renderer/canvas/Layer>}
|
||||
*/
|
||||
this.renderers_ = createRenderers(options.sources);
|
||||
|
||||
for (let r = 0, rr = this.renderers_.length; r < rr; ++r) {
|
||||
listen(this.renderers_[r], EventType.CHANGE,
|
||||
this.changed, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/TileQueue}
|
||||
*/
|
||||
this.tileQueue_ = new TileQueue(
|
||||
function() {
|
||||
return 1;
|
||||
},
|
||||
this.changed.bind(this));
|
||||
|
||||
const layerStatesArray = getLayerStatesArray(this.renderers_);
|
||||
const layerStates = {};
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The most recently requested frame state.
|
||||
* @type {module:ol/PluggableMap~FrameState}
|
||||
* @private
|
||||
*/
|
||||
this.requestedFrameState_;
|
||||
|
||||
/**
|
||||
* The most recently rendered image canvas.
|
||||
* @type {module:ol/ImageCanvas}
|
||||
* @private
|
||||
*/
|
||||
this.renderedImageCanvas_ = null;
|
||||
|
||||
/**
|
||||
* The most recently rendered revision.
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/PluggableMap~FrameState}
|
||||
*/
|
||||
this.frameState_ = {
|
||||
animate: false,
|
||||
coordinateToPixelTransform: createTransform(),
|
||||
extent: null,
|
||||
focus: null,
|
||||
index: 0,
|
||||
layerStates: layerStates,
|
||||
layerStatesArray: layerStatesArray,
|
||||
pixelRatio: 1,
|
||||
pixelToCoordinateTransform: createTransform(),
|
||||
postRenderFunctions: [],
|
||||
size: [0, 0],
|
||||
skippedFeatureUids: {},
|
||||
tileQueue: this.tileQueue_,
|
||||
time: Date.now(),
|
||||
usedTiles: {},
|
||||
viewState: /** @type {module:ol/View~State} */ ({
|
||||
rotation: 0
|
||||
}),
|
||||
viewHints: [],
|
||||
wantedTiles: {}
|
||||
};
|
||||
|
||||
ImageSource.call(this, {});
|
||||
|
||||
if (options.operation !== undefined) {
|
||||
this.setOperation(options.operation, options.lib);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inherits(RasterSource, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
* Set the operation.
|
||||
* @param {module:ol/source/Raster~Operation} operation New operation.
|
||||
* @param {Object=} opt_lib Functions that will be available to operations run
|
||||
* in a worker.
|
||||
* @api
|
||||
*/
|
||||
RasterSource.prototype.setOperation = function(operation, opt_lib) {
|
||||
this.worker_ = new Processor({
|
||||
operation: operation,
|
||||
imageOps: this.operationType_ === RasterOperationType.IMAGE,
|
||||
queue: 1,
|
||||
lib: opt_lib,
|
||||
threads: this.threads_
|
||||
});
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the stored frame state.
|
||||
* @param {module:ol/extent~Extent} extent The view extent (in map units).
|
||||
* @param {number} resolution The view resolution.
|
||||
* @param {module:ol/proj/Projection} projection The view projection.
|
||||
* @return {module:ol/PluggableMap~FrameState} The updated frame state.
|
||||
* @private
|
||||
*/
|
||||
RasterSource.prototype.updateFrameState_ = function(extent, resolution, projection) {
|
||||
|
||||
const frameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, this.frameState_));
|
||||
|
||||
frameState.viewState = /** @type {module:ol/View~State} */ (assign({}, frameState.viewState));
|
||||
|
||||
const center = getCenter(extent);
|
||||
|
||||
frameState.extent = extent.slice();
|
||||
frameState.focus = center;
|
||||
frameState.size[0] = Math.round(getWidth(extent) / resolution);
|
||||
frameState.size[1] = Math.round(getHeight(extent) / resolution);
|
||||
frameState.time = Date.now();
|
||||
frameState.animate = false;
|
||||
|
||||
const viewState = frameState.viewState;
|
||||
viewState.center = center;
|
||||
viewState.projection = projection;
|
||||
viewState.resolution = resolution;
|
||||
return frameState;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if all sources are ready.
|
||||
* @return {boolean} All sources are ready.
|
||||
* @private
|
||||
*/
|
||||
RasterSource.prototype.allSourcesReady_ = function() {
|
||||
let ready = true;
|
||||
let source;
|
||||
for (let i = 0, ii = this.renderers_.length; i < ii; ++i) {
|
||||
source = this.renderers_[i].getLayer().getSource();
|
||||
if (source.getState() !== SourceState.READY) {
|
||||
ready = false;
|
||||
break;
|
||||
for (let r = 0, rr = this.renderers_.length; r < rr; ++r) {
|
||||
listen(this.renderers_[r], EventType.CHANGE,
|
||||
this.changed, this);
|
||||
}
|
||||
}
|
||||
return ready;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/TileQueue}
|
||||
*/
|
||||
this.tileQueue_ = new TileQueue(
|
||||
function() {
|
||||
return 1;
|
||||
},
|
||||
this.changed.bind(this));
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
RasterSource.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
|
||||
if (!this.allSourcesReady_()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const frameState = this.updateFrameState_(extent, resolution, projection);
|
||||
this.requestedFrameState_ = frameState;
|
||||
|
||||
// check if we can't reuse the existing ol/ImageCanvas
|
||||
if (this.renderedImageCanvas_) {
|
||||
const renderedResolution = this.renderedImageCanvas_.getResolution();
|
||||
const renderedExtent = this.renderedImageCanvas_.getExtent();
|
||||
if (resolution !== renderedResolution || !equals(extent, renderedExtent)) {
|
||||
this.renderedImageCanvas_ = null;
|
||||
const layerStatesArray = getLayerStatesArray(this.renderers_);
|
||||
const layerStates = {};
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The most recently requested frame state.
|
||||
* @type {module:ol/PluggableMap~FrameState}
|
||||
* @private
|
||||
*/
|
||||
this.requestedFrameState_;
|
||||
|
||||
/**
|
||||
* The most recently rendered image canvas.
|
||||
* @type {module:ol/ImageCanvas}
|
||||
* @private
|
||||
*/
|
||||
this.renderedImageCanvas_ = null;
|
||||
|
||||
/**
|
||||
* The most recently rendered revision.
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedRevision_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/PluggableMap~FrameState}
|
||||
*/
|
||||
this.frameState_ = {
|
||||
animate: false,
|
||||
coordinateToPixelTransform: createTransform(),
|
||||
extent: null,
|
||||
focus: null,
|
||||
index: 0,
|
||||
layerStates: layerStates,
|
||||
layerStatesArray: layerStatesArray,
|
||||
pixelRatio: 1,
|
||||
pixelToCoordinateTransform: createTransform(),
|
||||
postRenderFunctions: [],
|
||||
size: [0, 0],
|
||||
skippedFeatureUids: {},
|
||||
tileQueue: this.tileQueue_,
|
||||
time: Date.now(),
|
||||
usedTiles: {},
|
||||
viewState: /** @type {module:ol/View~State} */ ({
|
||||
rotation: 0
|
||||
}),
|
||||
viewHints: [],
|
||||
wantedTiles: {}
|
||||
};
|
||||
|
||||
ImageSource.call(this, {});
|
||||
|
||||
if (options.operation !== undefined) {
|
||||
this.setOperation(options.operation, options.lib);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!this.renderedImageCanvas_ || this.getRevision() !== this.renderedRevision_) {
|
||||
this.processSources_();
|
||||
/**
|
||||
* Set the operation.
|
||||
* @param {module:ol/source/Raster~Operation} operation New operation.
|
||||
* @param {Object=} opt_lib Functions that will be available to operations run
|
||||
* in a worker.
|
||||
* @api
|
||||
*/
|
||||
setOperation(operation, opt_lib) {
|
||||
this.worker_ = new Processor({
|
||||
operation: operation,
|
||||
imageOps: this.operationType_ === RasterOperationType.IMAGE,
|
||||
queue: 1,
|
||||
lib: opt_lib,
|
||||
threads: this.threads_
|
||||
});
|
||||
this.changed();
|
||||
}
|
||||
|
||||
frameState.tileQueue.loadMoreTiles(16, 16);
|
||||
/**
|
||||
* Update the stored frame state.
|
||||
* @param {module:ol/extent~Extent} extent The view extent (in map units).
|
||||
* @param {number} resolution The view resolution.
|
||||
* @param {module:ol/proj/Projection} projection The view projection.
|
||||
* @return {module:ol/PluggableMap~FrameState} The updated frame state.
|
||||
* @private
|
||||
*/
|
||||
updateFrameState_(extent, resolution, projection) {
|
||||
|
||||
if (frameState.animate) {
|
||||
requestAnimationFrame(this.changed.bind(this));
|
||||
const frameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, this.frameState_));
|
||||
|
||||
frameState.viewState = /** @type {module:ol/View~State} */ (assign({}, frameState.viewState));
|
||||
|
||||
const center = getCenter(extent);
|
||||
|
||||
frameState.extent = extent.slice();
|
||||
frameState.focus = center;
|
||||
frameState.size[0] = Math.round(getWidth(extent) / resolution);
|
||||
frameState.size[1] = Math.round(getHeight(extent) / resolution);
|
||||
frameState.time = Date.now();
|
||||
frameState.animate = false;
|
||||
|
||||
const viewState = frameState.viewState;
|
||||
viewState.center = center;
|
||||
viewState.projection = projection;
|
||||
viewState.resolution = resolution;
|
||||
return frameState;
|
||||
}
|
||||
|
||||
return this.renderedImageCanvas_;
|
||||
};
|
||||
/**
|
||||
* Determine if all sources are ready.
|
||||
* @return {boolean} All sources are ready.
|
||||
* @private
|
||||
*/
|
||||
allSourcesReady_() {
|
||||
let ready = true;
|
||||
let source;
|
||||
for (let i = 0, ii = this.renderers_.length; i < ii; ++i) {
|
||||
source = this.renderers_[i].getLayer().getSource();
|
||||
if (source.getState() !== SourceState.READY) {
|
||||
ready = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getImage(extent, resolution, pixelRatio, projection) {
|
||||
if (!this.allSourcesReady_()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start processing source data.
|
||||
* @private
|
||||
*/
|
||||
RasterSource.prototype.processSources_ = function() {
|
||||
const frameState = this.requestedFrameState_;
|
||||
const len = this.renderers_.length;
|
||||
const imageDatas = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const imageData = getImageData(
|
||||
this.renderers_[i], frameState, frameState.layerStatesArray[i]);
|
||||
if (imageData) {
|
||||
imageDatas[i] = imageData;
|
||||
} else {
|
||||
const frameState = this.updateFrameState_(extent, resolution, projection);
|
||||
this.requestedFrameState_ = frameState;
|
||||
|
||||
// check if we can't reuse the existing ol/ImageCanvas
|
||||
if (this.renderedImageCanvas_) {
|
||||
const renderedResolution = this.renderedImageCanvas_.getResolution();
|
||||
const renderedExtent = this.renderedImageCanvas_.getExtent();
|
||||
if (resolution !== renderedResolution || !equals(extent, renderedExtent)) {
|
||||
this.renderedImageCanvas_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.renderedImageCanvas_ || this.getRevision() !== this.renderedRevision_) {
|
||||
this.processSources_();
|
||||
}
|
||||
|
||||
frameState.tileQueue.loadMoreTiles(16, 16);
|
||||
|
||||
if (frameState.animate) {
|
||||
requestAnimationFrame(this.changed.bind(this));
|
||||
}
|
||||
|
||||
return this.renderedImageCanvas_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start processing source data.
|
||||
* @private
|
||||
*/
|
||||
processSources_() {
|
||||
const frameState = this.requestedFrameState_;
|
||||
const len = this.renderers_.length;
|
||||
const imageDatas = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const imageData = getImageData(
|
||||
this.renderers_[i], frameState, frameState.layerStatesArray[i]);
|
||||
if (imageData) {
|
||||
imageDatas[i] = imageData;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const data = {};
|
||||
this.dispatchEvent(new RasterSourceEvent(RasterEventType.BEFOREOPERATIONS, frameState, data));
|
||||
this.worker_.process(imageDatas, data, this.onWorkerComplete_.bind(this, frameState));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when pixel processing is complete.
|
||||
* @param {module:ol/PluggableMap~FrameState} frameState The frame state.
|
||||
* @param {Error} err Any error during processing.
|
||||
* @param {ImageData} output The output image data.
|
||||
* @param {Object} data The user data.
|
||||
* @private
|
||||
*/
|
||||
onWorkerComplete_(frameState, err, output, data) {
|
||||
if (err || !output) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do nothing if extent or resolution changed
|
||||
const extent = frameState.extent;
|
||||
const resolution = frameState.viewState.resolution;
|
||||
if (resolution !== this.requestedFrameState_.viewState.resolution ||
|
||||
!equals(extent, this.requestedFrameState_.extent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let context;
|
||||
if (this.renderedImageCanvas_) {
|
||||
context = this.renderedImageCanvas_.getImage().getContext('2d');
|
||||
} else {
|
||||
const width = Math.round(getWidth(extent) / resolution);
|
||||
const height = Math.round(getHeight(extent) / resolution);
|
||||
context = createCanvasContext2D(width, height);
|
||||
this.renderedImageCanvas_ = new ImageCanvas(extent, resolution, 1, context.canvas);
|
||||
}
|
||||
context.putImageData(output, 0, 0);
|
||||
|
||||
this.changed();
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
this.dispatchEvent(new RasterSourceEvent(RasterEventType.AFTEROPERATIONS, frameState, data));
|
||||
}
|
||||
|
||||
const data = {};
|
||||
this.dispatchEvent(new RasterSourceEvent(RasterEventType.BEFOREOPERATIONS, frameState, data));
|
||||
this.worker_.process(imageDatas, data, this.onWorkerComplete_.bind(this, frameState));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when pixel processing is complete.
|
||||
* @param {module:ol/PluggableMap~FrameState} frameState The frame state.
|
||||
* @param {Error} err Any error during processing.
|
||||
* @param {ImageData} output The output image data.
|
||||
* @param {Object} data The user data.
|
||||
* @private
|
||||
*/
|
||||
RasterSource.prototype.onWorkerComplete_ = function(frameState, err, output, data) {
|
||||
if (err || !output) {
|
||||
return;
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getImageInternal() {
|
||||
return null; // not implemented
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing if extent or resolution changed
|
||||
const extent = frameState.extent;
|
||||
const resolution = frameState.viewState.resolution;
|
||||
if (resolution !== this.requestedFrameState_.viewState.resolution ||
|
||||
!equals(extent, this.requestedFrameState_.extent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let context;
|
||||
if (this.renderedImageCanvas_) {
|
||||
context = this.renderedImageCanvas_.getImage().getContext('2d');
|
||||
} else {
|
||||
const width = Math.round(getWidth(extent) / resolution);
|
||||
const height = Math.round(getHeight(extent) / resolution);
|
||||
context = createCanvasContext2D(width, height);
|
||||
this.renderedImageCanvas_ = new ImageCanvas(extent, resolution, 1, context.canvas);
|
||||
}
|
||||
context.putImageData(output, 0, 0);
|
||||
|
||||
this.changed();
|
||||
this.renderedRevision_ = this.getRevision();
|
||||
|
||||
this.dispatchEvent(new RasterSourceEvent(RasterEventType.AFTEROPERATIONS, frameState, data));
|
||||
};
|
||||
inherits(RasterSource, ImageSource);
|
||||
|
||||
|
||||
/**
|
||||
@@ -522,12 +525,4 @@ function createTileRenderer(source) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
RasterSource.prototype.getImageInternal = function() {
|
||||
return null; // not implemented
|
||||
};
|
||||
|
||||
|
||||
export default RasterSource;
|
||||
|
||||
@@ -51,63 +51,134 @@ import SourceState from '../source/State.js';
|
||||
* @param {module:ol/source/Source~Options} options Source options.
|
||||
* @api
|
||||
*/
|
||||
const Source = function(options) {
|
||||
class Source {
|
||||
constructor(options) {
|
||||
|
||||
BaseObject.call(this);
|
||||
BaseObject.call(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/proj/Projection}
|
||||
*/
|
||||
this.projection_ = getProjection(options.projection);
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/proj/Projection}
|
||||
*/
|
||||
this.projection_ = getProjection(options.projection);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/source/Source~Attribution}
|
||||
*/
|
||||
this.attributions_ = this.adaptAttributions_(options.attributions);
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/source/Source~Attribution}
|
||||
*/
|
||||
this.attributions_ = this.adaptAttributions_(options.attributions);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/State}
|
||||
*/
|
||||
this.state_ = options.state !== undefined ?
|
||||
options.state : SourceState.READY;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/State}
|
||||
*/
|
||||
this.state_ = options.state !== undefined ?
|
||||
options.state : SourceState.READY;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the attributions option into an attributions function.
|
||||
* @param {module:ol/source/Source~AttributionLike|undefined} attributionLike The attribution option.
|
||||
* @return {?module:ol/source/Source~Attribution} An attribution function (or null).
|
||||
*/
|
||||
adaptAttributions_(attributionLike) {
|
||||
if (!attributionLike) {
|
||||
return null;
|
||||
}
|
||||
if (Array.isArray(attributionLike)) {
|
||||
return function(frameState) {
|
||||
return attributionLike;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof attributionLike === 'function') {
|
||||
return attributionLike;
|
||||
}
|
||||
|
||||
return function(frameState) {
|
||||
return [attributionLike];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attribution function for the source.
|
||||
* @return {?module:ol/source/Source~Attribution} Attribution function.
|
||||
*/
|
||||
getAttributions() {
|
||||
return this.attributions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the projection of the source.
|
||||
* @return {module:ol/proj/Projection} Projection.
|
||||
* @api
|
||||
*/
|
||||
getProjection() {
|
||||
return this.projection_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {Array.<number>|undefined} Resolutions.
|
||||
*/
|
||||
getResolutions() {}
|
||||
|
||||
/**
|
||||
* Get the state of the source, see {@link module:ol/source/State~State} for possible states.
|
||||
* @return {module:ol/source/State} State.
|
||||
* @api
|
||||
*/
|
||||
getState() {
|
||||
return this.state_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean|undefined} Wrap X.
|
||||
*/
|
||||
getWrapX() {
|
||||
return this.wrapX_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the source and finally dispatches a 'change' event.
|
||||
* @api
|
||||
*/
|
||||
refresh() {
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attributions of the source.
|
||||
* @param {module:ol/source/Source~AttributionLike|undefined} attributions Attributions.
|
||||
* Can be passed as `string`, `Array<string>`, `{@link module:ol/source/Source~Attribution}`,
|
||||
* or `undefined`.
|
||||
* @api
|
||||
*/
|
||||
setAttributions(attributions) {
|
||||
this.attributions_ = this.adaptAttributions_(attributions);
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the source.
|
||||
* @param {module:ol/source/State} state State.
|
||||
* @protected
|
||||
*/
|
||||
setState(state) {
|
||||
this.state_ = state;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Source, BaseObject);
|
||||
|
||||
/**
|
||||
* Turns the attributions option into an attributions function.
|
||||
* @param {module:ol/source/Source~AttributionLike|undefined} attributionLike The attribution option.
|
||||
* @return {?module:ol/source/Source~Attribution} An attribution function (or null).
|
||||
*/
|
||||
Source.prototype.adaptAttributions_ = function(attributionLike) {
|
||||
if (!attributionLike) {
|
||||
return null;
|
||||
}
|
||||
if (Array.isArray(attributionLike)) {
|
||||
return function(frameState) {
|
||||
return attributionLike;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof attributionLike === 'function') {
|
||||
return attributionLike;
|
||||
}
|
||||
|
||||
return function(frameState) {
|
||||
return [attributionLike];
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
@@ -121,79 +192,4 @@ Source.prototype.adaptAttributions_ = function(attributionLike) {
|
||||
Source.prototype.forEachFeatureAtCoordinate = UNDEFINED;
|
||||
|
||||
|
||||
/**
|
||||
* Get the attribution function for the source.
|
||||
* @return {?module:ol/source/Source~Attribution} Attribution function.
|
||||
*/
|
||||
Source.prototype.getAttributions = function() {
|
||||
return this.attributions_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the projection of the source.
|
||||
* @return {module:ol/proj/Projection} Projection.
|
||||
* @api
|
||||
*/
|
||||
Source.prototype.getProjection = function() {
|
||||
return this.projection_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {Array.<number>|undefined} Resolutions.
|
||||
*/
|
||||
Source.prototype.getResolutions = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Get the state of the source, see {@link module:ol/source/State~State} for possible states.
|
||||
* @return {module:ol/source/State} State.
|
||||
* @api
|
||||
*/
|
||||
Source.prototype.getState = function() {
|
||||
return this.state_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean|undefined} Wrap X.
|
||||
*/
|
||||
Source.prototype.getWrapX = function() {
|
||||
return this.wrapX_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Refreshes the source and finally dispatches a 'change' event.
|
||||
* @api
|
||||
*/
|
||||
Source.prototype.refresh = function() {
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the attributions of the source.
|
||||
* @param {module:ol/source/Source~AttributionLike|undefined} attributions Attributions.
|
||||
* Can be passed as `string`, `Array<string>`, `{@link module:ol/source/Source~Attribution}`,
|
||||
* or `undefined`.
|
||||
* @api
|
||||
*/
|
||||
Source.prototype.setAttributions = function(attributions) {
|
||||
this.attributions_ = this.adaptAttributions_(attributions);
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the state of the source.
|
||||
* @param {module:ol/source/State} state State.
|
||||
* @protected
|
||||
*/
|
||||
Source.prototype.setState = function(state) {
|
||||
this.state_ = state;
|
||||
this.changed();
|
||||
};
|
||||
export default Source;
|
||||
|
||||
@@ -39,277 +39,263 @@ import {wrapX, getForProjection as getTileGridForProjection} from '../tilegrid.j
|
||||
* @param {module:ol/source/Tile~Options=} options SourceTile source options.
|
||||
* @api
|
||||
*/
|
||||
const TileSource = function(options) {
|
||||
class TileSource {
|
||||
constructor(options) {
|
||||
|
||||
Source.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
Source.call(this, {
|
||||
attributions: options.attributions,
|
||||
extent: options.extent,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.opaque_ = options.opaque !== undefined ? options.opaque : false;
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.opaque_ = options.opaque !== undefined ? options.opaque : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.tilePixelRatio_ = options.tilePixelRatio !== undefined ?
|
||||
options.tilePixelRatio : 1;
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.tilePixelRatio_ = options.tilePixelRatio !== undefined ?
|
||||
options.tilePixelRatio : 1;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/tilegrid/TileGrid}
|
||||
*/
|
||||
this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/tilegrid/TileGrid}
|
||||
*/
|
||||
this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/TileCache}
|
||||
*/
|
||||
this.tileCache = new TileCache(options.cacheSize);
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/TileCache}
|
||||
*/
|
||||
this.tileCache = new TileCache(options.cacheSize);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.tmpSize = [0, 0];
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.tmpSize = [0, 0];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.key_ = '';
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.key_ = '';
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~Options}
|
||||
*/
|
||||
this.tileOptions = {transition: options.transition};
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~Options}
|
||||
*/
|
||||
this.tileOptions = {transition: options.transition};
|
||||
|
||||
};
|
||||
|
||||
inherits(TileSource, Source);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can expire cache.
|
||||
*/
|
||||
TileSource.prototype.canExpireCache = function() {
|
||||
return this.tileCache.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
|
||||
*/
|
||||
TileSource.prototype.expireCache = function(projection, usedTiles) {
|
||||
const tileCache = this.getTileCacheForProjection(projection);
|
||||
if (tileCache) {
|
||||
tileCache.expireCache(usedTiles);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {number} z Zoom level.
|
||||
* @param {module:ol/TileRange} tileRange Tile range.
|
||||
* @param {function(module:ol/Tile):(boolean|undefined)} callback Called with each
|
||||
* loaded tile. If the callback returns `false`, the tile will not be
|
||||
* considered loaded.
|
||||
* @return {boolean} The tile range is fully covered with loaded tiles.
|
||||
*/
|
||||
TileSource.prototype.forEachLoadedTile = function(projection, z, tileRange, callback) {
|
||||
const tileCache = this.getTileCacheForProjection(projection);
|
||||
if (!tileCache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let covered = true;
|
||||
let tile, tileCoordKey, loaded;
|
||||
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
tileCoordKey = getKeyZXY(z, x, y);
|
||||
loaded = false;
|
||||
if (tileCache.containsKey(tileCoordKey)) {
|
||||
tile = /** @type {!module:ol/Tile} */ (tileCache.get(tileCoordKey));
|
||||
loaded = tile.getState() === TileState.LOADED;
|
||||
if (loaded) {
|
||||
loaded = (callback(tile) !== false);
|
||||
}
|
||||
}
|
||||
if (!loaded) {
|
||||
covered = false;
|
||||
}
|
||||
/**
|
||||
* @return {boolean} Can expire cache.
|
||||
*/
|
||||
canExpireCache() {
|
||||
return this.tileCache.canExpireCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
|
||||
*/
|
||||
expireCache(projection, usedTiles) {
|
||||
const tileCache = this.getTileCacheForProjection(projection);
|
||||
if (tileCache) {
|
||||
tileCache.expireCache(usedTiles);
|
||||
}
|
||||
}
|
||||
return covered;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {number} z Zoom level.
|
||||
* @param {module:ol/TileRange} tileRange Tile range.
|
||||
* @param {function(module:ol/Tile):(boolean|undefined)} callback Called with each
|
||||
* loaded tile. If the callback returns `false`, the tile will not be
|
||||
* considered loaded.
|
||||
* @return {boolean} The tile range is fully covered with loaded tiles.
|
||||
*/
|
||||
forEachLoadedTile(projection, z, tileRange, callback) {
|
||||
const tileCache = this.getTileCacheForProjection(projection);
|
||||
if (!tileCache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {number} Gutter.
|
||||
*/
|
||||
TileSource.prototype.getGutter = function(projection) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the key to be used for all tiles in the source.
|
||||
* @return {string} The key for all tiles.
|
||||
* @protected
|
||||
*/
|
||||
TileSource.prototype.getKey = function() {
|
||||
return this.key_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the value to be used as the key for all tiles in the source.
|
||||
* @param {string} key The key for tiles.
|
||||
* @protected
|
||||
*/
|
||||
TileSource.prototype.setKey = function(key) {
|
||||
if (this.key_ !== key) {
|
||||
this.key_ = key;
|
||||
this.changed();
|
||||
let covered = true;
|
||||
let tile, tileCoordKey, loaded;
|
||||
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
tileCoordKey = getKeyZXY(z, x, y);
|
||||
loaded = false;
|
||||
if (tileCache.containsKey(tileCoordKey)) {
|
||||
tile = /** @type {!module:ol/Tile} */ (tileCache.get(tileCoordKey));
|
||||
loaded = tile.getState() === TileState.LOADED;
|
||||
if (loaded) {
|
||||
loaded = (callback(tile) !== false);
|
||||
}
|
||||
}
|
||||
if (!loaded) {
|
||||
covered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return covered;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {number} Gutter.
|
||||
*/
|
||||
getGutter(projection) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {boolean} Opaque.
|
||||
*/
|
||||
TileSource.prototype.getOpaque = function(projection) {
|
||||
return this.opaque_;
|
||||
};
|
||||
/**
|
||||
* Return the key to be used for all tiles in the source.
|
||||
* @return {string} The key for all tiles.
|
||||
* @protected
|
||||
*/
|
||||
getKey() {
|
||||
return this.key_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value to be used as the key for all tiles in the source.
|
||||
* @param {string} key The key for tiles.
|
||||
* @protected
|
||||
*/
|
||||
setKey(key) {
|
||||
if (this.key_ !== key) {
|
||||
this.key_ = key;
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileSource.prototype.getResolutions = function() {
|
||||
return this.tileGrid.getResolutions();
|
||||
};
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {boolean} Opaque.
|
||||
*/
|
||||
getOpaque(projection) {
|
||||
return this.opaque_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getResolutions() {
|
||||
return this.tileGrid.getResolutions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
*/
|
||||
TileSource.prototype.getTile = function(z, x, y, pixelRatio, projection) {};
|
||||
/**
|
||||
* @abstract
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
*/
|
||||
getTile(z, x, y, pixelRatio, projection) {}
|
||||
|
||||
|
||||
/**
|
||||
* Return the tile grid of the tile source.
|
||||
* @return {module:ol/tilegrid/TileGrid} Tile grid.
|
||||
* @api
|
||||
*/
|
||||
TileSource.prototype.getTileGrid = function() {
|
||||
return this.tileGrid;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/tilegrid/TileGrid} Tile grid.
|
||||
*/
|
||||
TileSource.prototype.getTileGridForProjection = function(projection) {
|
||||
if (!this.tileGrid) {
|
||||
return getTileGridForProjection(projection);
|
||||
} else {
|
||||
/**
|
||||
* Return the tile grid of the tile source.
|
||||
* @return {module:ol/tilegrid/TileGrid} Tile grid.
|
||||
* @api
|
||||
*/
|
||||
getTileGrid() {
|
||||
return this.tileGrid;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/TileCache} Tile cache.
|
||||
* @protected
|
||||
*/
|
||||
TileSource.prototype.getTileCacheForProjection = function(projection) {
|
||||
const thisProj = this.getProjection();
|
||||
if (thisProj && !equivalent(thisProj, projection)) {
|
||||
return null;
|
||||
} else {
|
||||
return this.tileCache;
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/tilegrid/TileGrid} Tile grid.
|
||||
*/
|
||||
getTileGridForProjection(projection) {
|
||||
if (!this.tileGrid) {
|
||||
return getTileGridForProjection(projection);
|
||||
} else {
|
||||
return this.tileGrid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the tile pixel ratio for this source. Subclasses may override this
|
||||
* method, which is meant to return a supported pixel ratio that matches the
|
||||
* provided `pixelRatio` as close as possible.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @return {number} Tile pixel ratio.
|
||||
*/
|
||||
TileSource.prototype.getTilePixelRatio = function(pixelRatio) {
|
||||
return this.tilePixelRatio_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/size~Size} Tile size.
|
||||
*/
|
||||
TileSource.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
const tilePixelRatio = this.getTilePixelRatio(pixelRatio);
|
||||
const tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);
|
||||
if (tilePixelRatio == 1) {
|
||||
return tileSize;
|
||||
} else {
|
||||
return scaleSize(tileSize, tilePixelRatio, this.tmpSize);
|
||||
/**
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/TileCache} Tile cache.
|
||||
* @protected
|
||||
*/
|
||||
getTileCacheForProjection(projection) {
|
||||
const thisProj = this.getProjection();
|
||||
if (thisProj && !equivalent(thisProj, projection)) {
|
||||
return null;
|
||||
} else {
|
||||
return this.tileCache;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
|
||||
* is outside the resolution and extent range of the tile grid, `null` will be
|
||||
* returned.
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/proj/Projection=} opt_projection Projection.
|
||||
* @return {module:ol/tilecoord~TileCoord} Tile coordinate to be passed to the tileUrlFunction or
|
||||
* null if no tile URL should be created for the passed `tileCoord`.
|
||||
*/
|
||||
TileSource.prototype.getTileCoordForTileUrlFunction = function(tileCoord, opt_projection) {
|
||||
const projection = opt_projection !== undefined ?
|
||||
opt_projection : this.getProjection();
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
if (this.getWrapX() && projection.isGlobal()) {
|
||||
tileCoord = wrapX(tileGrid, tileCoord, projection);
|
||||
/**
|
||||
* Get the tile pixel ratio for this source. Subclasses may override this
|
||||
* method, which is meant to return a supported pixel ratio that matches the
|
||||
* provided `pixelRatio` as close as possible.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @return {number} Tile pixel ratio.
|
||||
*/
|
||||
getTilePixelRatio(pixelRatio) {
|
||||
return this.tilePixelRatio_;
|
||||
}
|
||||
return withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} z Z.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @return {module:ol/size~Size} Tile size.
|
||||
*/
|
||||
getTilePixelSize(z, pixelRatio, projection) {
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
const tilePixelRatio = this.getTilePixelRatio(pixelRatio);
|
||||
const tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);
|
||||
if (tilePixelRatio == 1) {
|
||||
return tileSize;
|
||||
} else {
|
||||
return scaleSize(tileSize, tilePixelRatio, this.tmpSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileSource.prototype.refresh = function() {
|
||||
this.tileCache.clear();
|
||||
this.changed();
|
||||
};
|
||||
/**
|
||||
* Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
|
||||
* is outside the resolution and extent range of the tile grid, `null` will be
|
||||
* returned.
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/proj/Projection=} opt_projection Projection.
|
||||
* @return {module:ol/tilecoord~TileCoord} Tile coordinate to be passed to the tileUrlFunction or
|
||||
* null if no tile URL should be created for the passed `tileCoord`.
|
||||
*/
|
||||
getTileCoordForTileUrlFunction(tileCoord, opt_projection) {
|
||||
const projection = opt_projection !== undefined ?
|
||||
opt_projection : this.getProjection();
|
||||
const tileGrid = this.getTileGridForProjection(projection);
|
||||
if (this.getWrapX() && projection.isGlobal()) {
|
||||
tileCoord = wrapX(tileGrid, tileCoord, projection);
|
||||
}
|
||||
return withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
refresh() {
|
||||
this.tileCache.clear();
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileSource, Source);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,162 +64,159 @@ import {appendParams} from '../uri.js';
|
||||
* @param {module:ol/source/TileArcGISRest~Options=} opt_options Tile ArcGIS Rest options.
|
||||
* @api
|
||||
*/
|
||||
const TileArcGISRest = function(opt_options) {
|
||||
class TileArcGISRest {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options || {};
|
||||
const options = opt_options || {};
|
||||
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
projection: options.projection,
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
projection: options.projection,
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/extent~Extent}
|
||||
*/
|
||||
this.tmpExtent_ = createEmpty();
|
||||
|
||||
this.setKey(this.getKeyForParams_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
* @return {string} The key for the current params.
|
||||
*/
|
||||
this.params_ = options.params || {};
|
||||
getKeyForParams_() {
|
||||
let i = 0;
|
||||
const res = [];
|
||||
for (const key in this.params_) {
|
||||
res[i++] = key + '-' + this.params_[key];
|
||||
}
|
||||
return res.join('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/extent~Extent}
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
this.tmpExtent_ = createEmpty();
|
||||
getParams() {
|
||||
return this.params_;
|
||||
}
|
||||
|
||||
this.setKey(this.getKeyForParams_());
|
||||
};
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/size~Size} tileSize Tile size.
|
||||
* @param {module:ol/extent~Extent} tileExtent Tile extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string|undefined} Request URL.
|
||||
* @private
|
||||
*/
|
||||
getRequestUrl_(tileCoord, tileSize, tileExtent, pixelRatio, projection, params) {
|
||||
|
||||
const urls = this.urls;
|
||||
if (!urls) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ArcGIS Server only wants the numeric portion of the projection ID.
|
||||
const srid = projection.getCode().split(':').pop();
|
||||
|
||||
params['SIZE'] = tileSize[0] + ',' + tileSize[1];
|
||||
params['BBOX'] = tileExtent.join(',');
|
||||
params['BBOXSR'] = srid;
|
||||
params['IMAGESR'] = srid;
|
||||
params['DPI'] = Math.round(
|
||||
params['DPI'] ? params['DPI'] * pixelRatio : 90 * pixelRatio
|
||||
);
|
||||
|
||||
let url;
|
||||
if (urls.length == 1) {
|
||||
url = urls[0];
|
||||
} else {
|
||||
const index = modulo(tileCoordHash(tileCoord), urls.length);
|
||||
url = urls[index];
|
||||
}
|
||||
|
||||
const modifiedUrl = url
|
||||
.replace(/MapServer\/?$/, 'MapServer/export')
|
||||
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
|
||||
return appendParams(modifiedUrl, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getTilePixelRatio(pixelRatio) {
|
||||
return /** @type {number} */ (pixelRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
fixedTileUrlFunction(tileCoord, pixelRatio, projection) {
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projection);
|
||||
}
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const tileExtent = tileGrid.getTileCoordExtent(
|
||||
tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(
|
||||
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
|
||||
}
|
||||
|
||||
// Apply default params and override with user specified values.
|
||||
const baseParams = {
|
||||
'F': 'image',
|
||||
'FORMAT': 'PNG32',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(baseParams, this.params_);
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, baseParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
updateParams(params) {
|
||||
assign(this.params_, params);
|
||||
this.setKey(this.getKeyForParams_());
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileArcGISRest, TileImage);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {string} The key for the current params.
|
||||
*/
|
||||
TileArcGISRest.prototype.getKeyForParams_ = function() {
|
||||
let i = 0;
|
||||
const res = [];
|
||||
for (const key in this.params_) {
|
||||
res[i++] = key + '-' + this.params_[key];
|
||||
}
|
||||
return res.join('/');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
TileArcGISRest.prototype.getParams = function() {
|
||||
return this.params_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/size~Size} tileSize Tile size.
|
||||
* @param {module:ol/extent~Extent} tileExtent Tile extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string|undefined} Request URL.
|
||||
* @private
|
||||
*/
|
||||
TileArcGISRest.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, params) {
|
||||
|
||||
const urls = this.urls;
|
||||
if (!urls) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ArcGIS Server only wants the numeric portion of the projection ID.
|
||||
const srid = projection.getCode().split(':').pop();
|
||||
|
||||
params['SIZE'] = tileSize[0] + ',' + tileSize[1];
|
||||
params['BBOX'] = tileExtent.join(',');
|
||||
params['BBOXSR'] = srid;
|
||||
params['IMAGESR'] = srid;
|
||||
params['DPI'] = Math.round(
|
||||
params['DPI'] ? params['DPI'] * pixelRatio : 90 * pixelRatio
|
||||
);
|
||||
|
||||
let url;
|
||||
if (urls.length == 1) {
|
||||
url = urls[0];
|
||||
} else {
|
||||
const index = modulo(tileCoordHash(tileCoord), urls.length);
|
||||
url = urls[index];
|
||||
}
|
||||
|
||||
const modifiedUrl = url
|
||||
.replace(/MapServer\/?$/, 'MapServer/export')
|
||||
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
|
||||
return appendParams(modifiedUrl, params);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileArcGISRest.prototype.getTilePixelRatio = function(pixelRatio) {
|
||||
return /** @type {number} */ (pixelRatio);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileArcGISRest.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projection);
|
||||
}
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const tileExtent = tileGrid.getTileCoordExtent(
|
||||
tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(
|
||||
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
|
||||
}
|
||||
|
||||
// Apply default params and override with user specified values.
|
||||
const baseParams = {
|
||||
'F': 'image',
|
||||
'FORMAT': 'PNG32',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(baseParams, this.params_);
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, baseParams);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
TileArcGISRest.prototype.updateParams = function(params) {
|
||||
assign(this.params_, params);
|
||||
this.setKey(this.getKeyForParams_());
|
||||
};
|
||||
export default TileArcGISRest;
|
||||
|
||||
@@ -17,64 +17,65 @@ import {getKeyZXY} from '../tilecoord.js';
|
||||
* @param {module:ol/size~Size} tileSize Tile size.
|
||||
* @param {string} text Text.
|
||||
*/
|
||||
const LabeledTile = function(tileCoord, tileSize, text) {
|
||||
class LabeledTile {
|
||||
constructor(tileCoord, tileSize, text) {
|
||||
|
||||
Tile.call(this, tileCoord, TileState.LOADED);
|
||||
Tile.call(this, tileCoord, TileState.LOADED);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.tileSize_ = tileSize;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/size~Size}
|
||||
*/
|
||||
this.tileSize_ = tileSize;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.text_ = text;
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.text_ = text;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
*/
|
||||
this.canvas_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
*/
|
||||
this.canvas_ = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image element for this tile.
|
||||
* @return {HTMLCanvasElement} Image.
|
||||
*/
|
||||
getImage() {
|
||||
if (this.canvas_) {
|
||||
return this.canvas_;
|
||||
} else {
|
||||
const tileSize = this.tileSize_;
|
||||
const context = createCanvasContext2D(tileSize[0], tileSize[1]);
|
||||
|
||||
context.strokeStyle = 'black';
|
||||
context.strokeRect(0.5, 0.5, tileSize[0] + 0.5, tileSize[1] + 0.5);
|
||||
|
||||
context.fillStyle = 'black';
|
||||
context.textAlign = 'center';
|
||||
context.textBaseline = 'middle';
|
||||
context.font = '24px sans-serif';
|
||||
context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
|
||||
|
||||
this.canvas_ = context.canvas;
|
||||
return context.canvas;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
load() {}
|
||||
}
|
||||
|
||||
};
|
||||
inherits(LabeledTile, Tile);
|
||||
|
||||
|
||||
/**
|
||||
* Get the image element for this tile.
|
||||
* @return {HTMLCanvasElement} Image.
|
||||
*/
|
||||
LabeledTile.prototype.getImage = function() {
|
||||
if (this.canvas_) {
|
||||
return this.canvas_;
|
||||
} else {
|
||||
const tileSize = this.tileSize_;
|
||||
const context = createCanvasContext2D(tileSize[0], tileSize[1]);
|
||||
|
||||
context.strokeStyle = 'black';
|
||||
context.strokeRect(0.5, 0.5, tileSize[0] + 0.5, tileSize[1] + 0.5);
|
||||
|
||||
context.fillStyle = 'black';
|
||||
context.textAlign = 'center';
|
||||
context.textBaseline = 'middle';
|
||||
context.font = '24px sans-serif';
|
||||
context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
|
||||
|
||||
this.canvas_ = context.canvas;
|
||||
return context.canvas;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
LabeledTile.prototype.load = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {module:ol/proj~ProjectionLike} projection Projection.
|
||||
@@ -96,38 +97,39 @@ LabeledTile.prototype.load = function() {};
|
||||
* @param {module:ol/source/TileDebug~Options=} options Debug tile options.
|
||||
* @api
|
||||
*/
|
||||
const TileDebug = function(options) {
|
||||
class TileDebug {
|
||||
constructor(options) {
|
||||
|
||||
TileSource.call(this, {
|
||||
opaque: false,
|
||||
projection: options.projection,
|
||||
tileGrid: options.tileGrid,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true
|
||||
});
|
||||
TileSource.call(this, {
|
||||
opaque: false,
|
||||
projection: options.projection,
|
||||
tileGrid: options.tileGrid,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getTile(z, x, y) {
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
return /** @type {!module:ol/source/TileDebug~LabeledTile} */ (this.tileCache.get(tileCoordKey));
|
||||
} else {
|
||||
const tileSize = toSize(this.tileGrid.getTileSize(z));
|
||||
const tileCoord = [z, x, y];
|
||||
const textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
|
||||
const text = !textTileCoord ? '' :
|
||||
this.getTileCoordForTileUrlFunction(textTileCoord).toString();
|
||||
const tile = new LabeledTile(tileCoord, tileSize, text);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileDebug, TileSource);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileDebug.prototype.getTile = function(z, x, y) {
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
return /** @type {!module:ol/source/TileDebug~LabeledTile} */ (this.tileCache.get(tileCoordKey));
|
||||
} else {
|
||||
const tileSize = toSize(this.tileGrid.getTileSize(z));
|
||||
const tileCoord = [z, x, y];
|
||||
const textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
|
||||
const text = !textTileCoord ? '' :
|
||||
this.getTileCoordForTileUrlFunction(textTileCoord).toString();
|
||||
const tile = new LabeledTile(tileCoord, tileSize, text);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default TileDebug;
|
||||
|
||||
@@ -64,344 +64,334 @@ import {getForProjection as getTileGridForProjection} from '../tilegrid.js';
|
||||
* @param {module:ol/source/TileImage~Options=} options Image tile options.
|
||||
* @api
|
||||
*/
|
||||
const TileImage = function(options) {
|
||||
class TileImage {
|
||||
constructor(options) {
|
||||
|
||||
UrlTile.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
extent: options.extent,
|
||||
opaque: options.opaque,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction ?
|
||||
options.tileLoadFunction : defaultTileLoadFunction,
|
||||
tilePixelRatio: options.tilePixelRatio,
|
||||
tileUrlFunction: options.tileUrlFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX,
|
||||
transition: options.transition
|
||||
});
|
||||
UrlTile.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
extent: options.extent,
|
||||
opaque: options.opaque,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction ?
|
||||
options.tileLoadFunction : defaultTileLoadFunction,
|
||||
tilePixelRatio: options.tilePixelRatio,
|
||||
tileUrlFunction: options.tileUrlFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {function(new: module:ol/ImageTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
|
||||
* ?string, module:ol/Tile~LoadFunction, module:ol/Tile~Options=)}
|
||||
*/
|
||||
this.tileClass = options.tileClass !== undefined ?
|
||||
options.tileClass : ImageTile;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Object.<string, module:ol/TileCache>}
|
||||
*/
|
||||
this.tileCacheForProjection = {};
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Object.<string, module:ol/tilegrid/TileGrid>}
|
||||
*/
|
||||
this.tileGridForProjection = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderReprojectionEdges_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
canExpireCache() {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.canExpireCache.call(this);
|
||||
}
|
||||
if (this.tileCache.canExpireCache()) {
|
||||
return true;
|
||||
} else {
|
||||
for (const key in this.tileCacheForProjection) {
|
||||
if (this.tileCacheForProjection[key].canExpireCache()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
expireCache(projection, usedTiles) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
UrlTile.prototype.expireCache.call(this, projection, usedTiles);
|
||||
return;
|
||||
}
|
||||
const usedTileCache = this.getTileCacheForProjection(projection);
|
||||
|
||||
this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
|
||||
for (const id in this.tileCacheForProjection) {
|
||||
const tileCache = this.tileCacheForProjection[id];
|
||||
tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getGutter(projection) {
|
||||
if (ENABLE_RASTER_REPROJECTION &&
|
||||
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.getGutterInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?string}
|
||||
* @return {number} Gutter.
|
||||
*/
|
||||
this.crossOrigin =
|
||||
options.crossOrigin !== undefined ? options.crossOrigin : null;
|
||||
getGutterInternal() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {function(new: module:ol/ImageTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
|
||||
* ?string, module:ol/Tile~LoadFunction, module:ol/Tile~Options=)}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.tileClass = options.tileClass !== undefined ?
|
||||
options.tileClass : ImageTile;
|
||||
getOpaque(projection) {
|
||||
if (ENABLE_RASTER_REPROJECTION &&
|
||||
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
|
||||
return false;
|
||||
} else {
|
||||
return UrlTile.prototype.getOpaque.call(this, projection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Object.<string, module:ol/TileCache>}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.tileCacheForProjection = {};
|
||||
getTileGridForProjection(projection) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.getTileGridForProjection.call(this, projection);
|
||||
}
|
||||
const thisProj = this.getProjection();
|
||||
if (this.tileGrid && (!thisProj || equivalent(thisProj, projection))) {
|
||||
return this.tileGrid;
|
||||
} else {
|
||||
const projKey = getUid(projection).toString();
|
||||
if (!(projKey in this.tileGridForProjection)) {
|
||||
this.tileGridForProjection[projKey] = getTileGridForProjection(projection);
|
||||
}
|
||||
return (
|
||||
/** @type {!module:ol/tilegrid/TileGrid} */ (this.tileGridForProjection[projKey])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Object.<string, module:ol/tilegrid/TileGrid>}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.tileGridForProjection = {};
|
||||
getTileCacheForProjection(projection) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.getTileCacheForProjection.call(this, projection);
|
||||
}
|
||||
const thisProj = this.getProjection(); if (!thisProj || equivalent(thisProj, projection)) {
|
||||
return this.tileCache;
|
||||
} else {
|
||||
const projKey = getUid(projection).toString();
|
||||
if (!(projKey in this.tileCacheForProjection)) {
|
||||
this.tileCacheForProjection[projKey] = new TileCache(this.tileCache.highWaterMark);
|
||||
}
|
||||
return this.tileCacheForProjection[projKey];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {string} key The key set on the tile.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;
|
||||
createTile_(z, x, y, pixelRatio, projection, key) {
|
||||
const tileCoord = [z, x, y];
|
||||
const urlTileCoord = this.getTileCoordForTileUrlFunction(
|
||||
tileCoord, projection);
|
||||
const tileUrl = urlTileCoord ?
|
||||
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
|
||||
const tile = new this.tileClass(
|
||||
tileCoord,
|
||||
tileUrl !== undefined ? TileState.IDLE : TileState.EMPTY,
|
||||
tileUrl !== undefined ? tileUrl : '',
|
||||
this.crossOrigin,
|
||||
this.tileLoadFunction,
|
||||
this.tileOptions);
|
||||
tile.key = key;
|
||||
listen(tile, EventType.CHANGE,
|
||||
this.handleTileChange, this);
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.renderReprojectionEdges_ = false;
|
||||
};
|
||||
getTile(z, x, y, pixelRatio, projection) {
|
||||
const sourceProjection = /** @type {!module:ol/proj/Projection} */ (this.getProjection());
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
!sourceProjection || !projection || equivalent(sourceProjection, projection)) {
|
||||
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection || projection);
|
||||
} else {
|
||||
const cache = this.getTileCacheForProjection(projection);
|
||||
const tileCoord = [z, x, y];
|
||||
let tile;
|
||||
const tileCoordKey = getKey(tileCoord);
|
||||
if (cache.containsKey(tileCoordKey)) {
|
||||
tile = /** @type {!module:ol/Tile} */ (cache.get(tileCoordKey));
|
||||
}
|
||||
const key = this.getKey();
|
||||
if (tile && tile.key == key) {
|
||||
return tile;
|
||||
} else {
|
||||
const sourceTileGrid = this.getTileGridForProjection(sourceProjection);
|
||||
const targetTileGrid = this.getTileGridForProjection(projection);
|
||||
const wrappedTileCoord =
|
||||
this.getTileCoordForTileUrlFunction(tileCoord, projection);
|
||||
const newTile = new ReprojTile(
|
||||
sourceProjection, sourceTileGrid,
|
||||
projection, targetTileGrid,
|
||||
tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
|
||||
this.getGutterInternal(),
|
||||
function(z, x, y, pixelRatio) {
|
||||
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
|
||||
}.bind(this), this.reprojectionErrorThreshold_,
|
||||
this.renderReprojectionEdges_);
|
||||
newTile.key = key;
|
||||
|
||||
if (tile) {
|
||||
newTile.interimTile = tile;
|
||||
newTile.refreshInterimChain();
|
||||
cache.replace(tileCoordKey, newTile);
|
||||
} else {
|
||||
cache.set(tileCoordKey, newTile);
|
||||
}
|
||||
return newTile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {!module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
* @protected
|
||||
*/
|
||||
getTileInternal(z, x, y, pixelRatio, projection) {
|
||||
let tile = null;
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
const key = this.getKey();
|
||||
if (!this.tileCache.containsKey(tileCoordKey)) {
|
||||
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
} else {
|
||||
tile = this.tileCache.get(tileCoordKey);
|
||||
if (tile.key != key) {
|
||||
// The source's params changed. If the tile has an interim tile and if we
|
||||
// can use it then we use it. Otherwise we create a new tile. In both
|
||||
// cases we attempt to assign an interim tile to the new tile.
|
||||
const interimTile = tile;
|
||||
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
|
||||
|
||||
//make the new tile the head of the list,
|
||||
if (interimTile.getState() == TileState.IDLE) {
|
||||
//the old tile hasn't begun loading yet, and is now outdated, so we can simply discard it
|
||||
tile.interimTile = interimTile.interimTile;
|
||||
} else {
|
||||
tile.interimTile = interimTile;
|
||||
}
|
||||
tile.refreshInterimChain();
|
||||
this.tileCache.replace(tileCoordKey, tile);
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to render reprojection edges or not (usually for debugging).
|
||||
* @param {boolean} render Render the edges.
|
||||
* @api
|
||||
*/
|
||||
setRenderReprojectionEdges(render) {
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
this.renderReprojectionEdges_ == render) {
|
||||
return;
|
||||
}
|
||||
this.renderReprojectionEdges_ = render;
|
||||
for (const id in this.tileCacheForProjection) {
|
||||
this.tileCacheForProjection[id].clear();
|
||||
}
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile grid to use when reprojecting the tiles to the given
|
||||
* projection instead of the default tile grid for the projection.
|
||||
*
|
||||
* This can be useful when the default tile grid cannot be created
|
||||
* (e.g. projection has no extent defined) or
|
||||
* for optimization reasons (custom tile size, resolutions, ...).
|
||||
*
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {module:ol/tilegrid/TileGrid} tilegrid Tile grid to use for the projection.
|
||||
* @api
|
||||
*/
|
||||
setTileGridForProjection(projection, tilegrid) {
|
||||
if (ENABLE_RASTER_REPROJECTION) {
|
||||
const proj = getProjection(projection);
|
||||
if (proj) {
|
||||
const projKey = getUid(proj).toString();
|
||||
if (!(projKey in this.tileGridForProjection)) {
|
||||
this.tileGridForProjection[projKey] = tilegrid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileImage, UrlTile);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.canExpireCache = function() {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.canExpireCache.call(this);
|
||||
}
|
||||
if (this.tileCache.canExpireCache()) {
|
||||
return true;
|
||||
} else {
|
||||
for (const key in this.tileCacheForProjection) {
|
||||
if (this.tileCacheForProjection[key].canExpireCache()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.expireCache = function(projection, usedTiles) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
UrlTile.prototype.expireCache.call(this, projection, usedTiles);
|
||||
return;
|
||||
}
|
||||
const usedTileCache = this.getTileCacheForProjection(projection);
|
||||
|
||||
this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
|
||||
for (const id in this.tileCacheForProjection) {
|
||||
const tileCache = this.tileCacheForProjection[id];
|
||||
tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.getGutter = function(projection) {
|
||||
if (ENABLE_RASTER_REPROJECTION &&
|
||||
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.getGutterInternal();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @return {number} Gutter.
|
||||
*/
|
||||
TileImage.prototype.getGutterInternal = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.getOpaque = function(projection) {
|
||||
if (ENABLE_RASTER_REPROJECTION &&
|
||||
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
|
||||
return false;
|
||||
} else {
|
||||
return UrlTile.prototype.getOpaque.call(this, projection);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.getTileGridForProjection = function(projection) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.getTileGridForProjection.call(this, projection);
|
||||
}
|
||||
const thisProj = this.getProjection();
|
||||
if (this.tileGrid && (!thisProj || equivalent(thisProj, projection))) {
|
||||
return this.tileGrid;
|
||||
} else {
|
||||
const projKey = getUid(projection).toString();
|
||||
if (!(projKey in this.tileGridForProjection)) {
|
||||
this.tileGridForProjection[projKey] = getTileGridForProjection(projection);
|
||||
}
|
||||
return (
|
||||
/** @type {!module:ol/tilegrid/TileGrid} */ (this.tileGridForProjection[projKey])
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.getTileCacheForProjection = function(projection) {
|
||||
if (!ENABLE_RASTER_REPROJECTION) {
|
||||
return UrlTile.prototype.getTileCacheForProjection.call(this, projection);
|
||||
}
|
||||
const thisProj = this.getProjection(); if (!thisProj || equivalent(thisProj, projection)) {
|
||||
return this.tileCache;
|
||||
} else {
|
||||
const projKey = getUid(projection).toString();
|
||||
if (!(projKey in this.tileCacheForProjection)) {
|
||||
this.tileCacheForProjection[projKey] = new TileCache(this.tileCache.highWaterMark);
|
||||
}
|
||||
return this.tileCacheForProjection[projKey];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {string} key The key set on the tile.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
* @private
|
||||
*/
|
||||
TileImage.prototype.createTile_ = function(z, x, y, pixelRatio, projection, key) {
|
||||
const tileCoord = [z, x, y];
|
||||
const urlTileCoord = this.getTileCoordForTileUrlFunction(
|
||||
tileCoord, projection);
|
||||
const tileUrl = urlTileCoord ?
|
||||
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
|
||||
const tile = new this.tileClass(
|
||||
tileCoord,
|
||||
tileUrl !== undefined ? TileState.IDLE : TileState.EMPTY,
|
||||
tileUrl !== undefined ? tileUrl : '',
|
||||
this.crossOrigin,
|
||||
this.tileLoadFunction,
|
||||
this.tileOptions);
|
||||
tile.key = key;
|
||||
listen(tile, EventType.CHANGE,
|
||||
this.handleTileChange, this);
|
||||
return tile;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileImage.prototype.getTile = function(z, x, y, pixelRatio, projection) {
|
||||
const sourceProjection = /** @type {!module:ol/proj/Projection} */ (this.getProjection());
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
!sourceProjection || !projection || equivalent(sourceProjection, projection)) {
|
||||
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection || projection);
|
||||
} else {
|
||||
const cache = this.getTileCacheForProjection(projection);
|
||||
const tileCoord = [z, x, y];
|
||||
let tile;
|
||||
const tileCoordKey = getKey(tileCoord);
|
||||
if (cache.containsKey(tileCoordKey)) {
|
||||
tile = /** @type {!module:ol/Tile} */ (cache.get(tileCoordKey));
|
||||
}
|
||||
const key = this.getKey();
|
||||
if (tile && tile.key == key) {
|
||||
return tile;
|
||||
} else {
|
||||
const sourceTileGrid = this.getTileGridForProjection(sourceProjection);
|
||||
const targetTileGrid = this.getTileGridForProjection(projection);
|
||||
const wrappedTileCoord =
|
||||
this.getTileCoordForTileUrlFunction(tileCoord, projection);
|
||||
const newTile = new ReprojTile(
|
||||
sourceProjection, sourceTileGrid,
|
||||
projection, targetTileGrid,
|
||||
tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
|
||||
this.getGutterInternal(),
|
||||
function(z, x, y, pixelRatio) {
|
||||
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
|
||||
}.bind(this), this.reprojectionErrorThreshold_,
|
||||
this.renderReprojectionEdges_);
|
||||
newTile.key = key;
|
||||
|
||||
if (tile) {
|
||||
newTile.interimTile = tile;
|
||||
newTile.refreshInterimChain();
|
||||
cache.replace(tileCoordKey, newTile);
|
||||
} else {
|
||||
cache.set(tileCoordKey, newTile);
|
||||
}
|
||||
return newTile;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} z Tile coordinate z.
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {!module:ol/proj/Projection} projection Projection.
|
||||
* @return {!module:ol/Tile} Tile.
|
||||
* @protected
|
||||
*/
|
||||
TileImage.prototype.getTileInternal = function(z, x, y, pixelRatio, projection) {
|
||||
let tile = null;
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
const key = this.getKey();
|
||||
if (!this.tileCache.containsKey(tileCoordKey)) {
|
||||
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
|
||||
this.tileCache.set(tileCoordKey, tile);
|
||||
} else {
|
||||
tile = this.tileCache.get(tileCoordKey);
|
||||
if (tile.key != key) {
|
||||
// The source's params changed. If the tile has an interim tile and if we
|
||||
// can use it then we use it. Otherwise we create a new tile. In both
|
||||
// cases we attempt to assign an interim tile to the new tile.
|
||||
const interimTile = tile;
|
||||
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
|
||||
|
||||
//make the new tile the head of the list,
|
||||
if (interimTile.getState() == TileState.IDLE) {
|
||||
//the old tile hasn't begun loading yet, and is now outdated, so we can simply discard it
|
||||
tile.interimTile = interimTile.interimTile;
|
||||
} else {
|
||||
tile.interimTile = interimTile;
|
||||
}
|
||||
tile.refreshInterimChain();
|
||||
this.tileCache.replace(tileCoordKey, tile);
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether to render reprojection edges or not (usually for debugging).
|
||||
* @param {boolean} render Render the edges.
|
||||
* @api
|
||||
*/
|
||||
TileImage.prototype.setRenderReprojectionEdges = function(render) {
|
||||
if (!ENABLE_RASTER_REPROJECTION ||
|
||||
this.renderReprojectionEdges_ == render) {
|
||||
return;
|
||||
}
|
||||
this.renderReprojectionEdges_ = render;
|
||||
for (const id in this.tileCacheForProjection) {
|
||||
this.tileCacheForProjection[id].clear();
|
||||
}
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the tile grid to use when reprojecting the tiles to the given
|
||||
* projection instead of the default tile grid for the projection.
|
||||
*
|
||||
* This can be useful when the default tile grid cannot be created
|
||||
* (e.g. projection has no extent defined) or
|
||||
* for optimization reasons (custom tile size, resolutions, ...).
|
||||
*
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {module:ol/tilegrid/TileGrid} tilegrid Tile grid to use for the projection.
|
||||
* @api
|
||||
*/
|
||||
TileImage.prototype.setTileGridForProjection = function(projection, tilegrid) {
|
||||
if (ENABLE_RASTER_REPROJECTION) {
|
||||
const proj = getProjection(projection);
|
||||
if (proj) {
|
||||
const projKey = getUid(proj).toString();
|
||||
if (!(projKey in this.tileGridForProjection)) {
|
||||
this.tileGridForProjection[projKey] = tilegrid;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/ImageTile} imageTile Image tile.
|
||||
* @param {string} src Source.
|
||||
|
||||
@@ -53,137 +53,136 @@ import {createXYZ, extentFromProjection} from '../tilegrid.js';
|
||||
* @param {module:ol/source/TileJSON~Options=} options TileJSON options.
|
||||
* @api
|
||||
*/
|
||||
const TileJSON = function(options) {
|
||||
class TileJSON {
|
||||
constructor(options) {
|
||||
|
||||
/**
|
||||
* @type {TileJSON}
|
||||
* @private
|
||||
*/
|
||||
this.tileJSON_ = null;
|
||||
/**
|
||||
* @type {TileJSON}
|
||||
* @private
|
||||
*/
|
||||
this.tileJSON_ = null;
|
||||
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
projection: getProjection('EPSG:3857'),
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
state: SourceState.LOADING,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
projection: getProjection('EPSG:3857'),
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
state: SourceState.LOADING,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
if (options.url) {
|
||||
if (options.jsonp) {
|
||||
requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
|
||||
this.handleTileJSONError.bind(this));
|
||||
if (options.url) {
|
||||
if (options.jsonp) {
|
||||
requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
|
||||
this.handleTileJSONError.bind(this));
|
||||
} else {
|
||||
const client = new XMLHttpRequest();
|
||||
client.addEventListener('load', this.onXHRLoad_.bind(this));
|
||||
client.addEventListener('error', this.onXHRError_.bind(this));
|
||||
client.open('GET', options.url);
|
||||
client.send();
|
||||
}
|
||||
} else if (options.tileJSON) {
|
||||
this.handleTileJSONResponse(options.tileJSON);
|
||||
} else {
|
||||
const client = new XMLHttpRequest();
|
||||
client.addEventListener('load', this.onXHRLoad_.bind(this));
|
||||
client.addEventListener('error', this.onXHRError_.bind(this));
|
||||
client.open('GET', options.url);
|
||||
client.send();
|
||||
assert(false, 51); // Either `url` or `tileJSON` options must be provided
|
||||
}
|
||||
} else if (options.tileJSON) {
|
||||
this.handleTileJSONResponse(options.tileJSON);
|
||||
} else {
|
||||
assert(false, 51); // Either `url` or `tileJSON` options must be provided
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event The load event.
|
||||
*/
|
||||
onXHRLoad_(event) {
|
||||
const client = /** @type {XMLHttpRequest} */ (event.target);
|
||||
// status will be 0 for file:// urls
|
||||
if (!client.status || client.status >= 200 && client.status < 300) {
|
||||
let response;
|
||||
try {
|
||||
response = /** @type {TileJSON} */(JSON.parse(client.responseText));
|
||||
} catch (err) {
|
||||
this.handleTileJSONError();
|
||||
return;
|
||||
}
|
||||
this.handleTileJSONResponse(response);
|
||||
} else {
|
||||
this.handleTileJSONError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event The error event.
|
||||
*/
|
||||
onXHRError_(event) {
|
||||
this.handleTileJSONError();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {TileJSON} The tilejson object.
|
||||
* @api
|
||||
*/
|
||||
getTileJSON() {
|
||||
return this.tileJSON_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {TileJSON} tileJSON Tile JSON.
|
||||
*/
|
||||
handleTileJSONResponse(tileJSON) {
|
||||
|
||||
const epsg4326Projection = getProjection('EPSG:4326');
|
||||
|
||||
const sourceProjection = this.getProjection();
|
||||
let extent;
|
||||
if (tileJSON.bounds !== undefined) {
|
||||
const transform = getTransformFromProjections(
|
||||
epsg4326Projection, sourceProjection);
|
||||
extent = applyTransform(tileJSON.bounds, transform);
|
||||
}
|
||||
|
||||
const minZoom = tileJSON.minzoom || 0;
|
||||
const maxZoom = tileJSON.maxzoom || 22;
|
||||
const tileGrid = createXYZ({
|
||||
extent: extentFromProjection(sourceProjection),
|
||||
maxZoom: maxZoom,
|
||||
minZoom: minZoom
|
||||
});
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);
|
||||
|
||||
if (tileJSON.attribution !== undefined && !this.getAttributions()) {
|
||||
const attributionExtent = extent !== undefined ?
|
||||
extent : epsg4326Projection.getExtent();
|
||||
|
||||
this.setAttributions(function(frameState) {
|
||||
if (intersects(attributionExtent, frameState.extent)) {
|
||||
return [tileJSON.attribution];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
}
|
||||
this.tileJSON_ = tileJSON;
|
||||
this.setState(SourceState.READY);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleTileJSONError() {
|
||||
this.setState(SourceState.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileJSON, TileImage);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event The load event.
|
||||
*/
|
||||
TileJSON.prototype.onXHRLoad_ = function(event) {
|
||||
const client = /** @type {XMLHttpRequest} */ (event.target);
|
||||
// status will be 0 for file:// urls
|
||||
if (!client.status || client.status >= 200 && client.status < 300) {
|
||||
let response;
|
||||
try {
|
||||
response = /** @type {TileJSON} */(JSON.parse(client.responseText));
|
||||
} catch (err) {
|
||||
this.handleTileJSONError();
|
||||
return;
|
||||
}
|
||||
this.handleTileJSONResponse(response);
|
||||
} else {
|
||||
this.handleTileJSONError();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} event The error event.
|
||||
*/
|
||||
TileJSON.prototype.onXHRError_ = function(event) {
|
||||
this.handleTileJSONError();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {TileJSON} The tilejson object.
|
||||
* @api
|
||||
*/
|
||||
TileJSON.prototype.getTileJSON = function() {
|
||||
return this.tileJSON_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {TileJSON} tileJSON Tile JSON.
|
||||
*/
|
||||
TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
|
||||
|
||||
const epsg4326Projection = getProjection('EPSG:4326');
|
||||
|
||||
const sourceProjection = this.getProjection();
|
||||
let extent;
|
||||
if (tileJSON.bounds !== undefined) {
|
||||
const transform = getTransformFromProjections(
|
||||
epsg4326Projection, sourceProjection);
|
||||
extent = applyTransform(tileJSON.bounds, transform);
|
||||
}
|
||||
|
||||
const minZoom = tileJSON.minzoom || 0;
|
||||
const maxZoom = tileJSON.maxzoom || 22;
|
||||
const tileGrid = createXYZ({
|
||||
extent: extentFromProjection(sourceProjection),
|
||||
maxZoom: maxZoom,
|
||||
minZoom: minZoom
|
||||
});
|
||||
this.tileGrid = tileGrid;
|
||||
|
||||
this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);
|
||||
|
||||
if (tileJSON.attribution !== undefined && !this.getAttributions()) {
|
||||
const attributionExtent = extent !== undefined ?
|
||||
extent : epsg4326Projection.getExtent();
|
||||
|
||||
this.setAttributions(function(frameState) {
|
||||
if (intersects(attributionExtent, frameState.extent)) {
|
||||
return [tileJSON.attribution];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
}
|
||||
this.tileJSON_ = tileJSON;
|
||||
this.setState(SourceState.READY);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
TileJSON.prototype.handleTileJSONError = function() {
|
||||
this.setState(SourceState.ERROR);
|
||||
};
|
||||
export default TileJSON;
|
||||
|
||||
@@ -80,320 +80,315 @@ import {appendParams} from '../uri.js';
|
||||
* @param {module:ol/source/TileWMS~Options=} [opt_options] Tile WMS options.
|
||||
* @api
|
||||
*/
|
||||
const TileWMS = function(opt_options) {
|
||||
class TileWMS {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options || {};
|
||||
const options = opt_options || {};
|
||||
|
||||
const params = options.params || {};
|
||||
const params = options.params || {};
|
||||
|
||||
const transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
|
||||
const transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
|
||||
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
opaque: !transparent,
|
||||
projection: options.projection,
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
tileClass: options.tileClass,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
TileImage.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
crossOrigin: options.crossOrigin,
|
||||
opaque: !transparent,
|
||||
projection: options.projection,
|
||||
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
|
||||
tileClass: options.tileClass,
|
||||
tileGrid: options.tileGrid,
|
||||
tileLoadFunction: options.tileLoadFunction,
|
||||
url: options.url,
|
||||
urls: options.urls,
|
||||
wrapX: options.wrapX !== undefined ? options.wrapX : true,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.gutter_ = options.gutter !== undefined ? options.gutter : 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = params;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.v13_ = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/WMSServerType|undefined}
|
||||
*/
|
||||
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/extent~Extent}
|
||||
*/
|
||||
this.tmpExtent_ = createEmpty();
|
||||
|
||||
this.updateV13_();
|
||||
this.setKey(this.getKeyForParams_());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
|
||||
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
|
||||
* constructed.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
|
||||
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
|
||||
* in the `LAYERS` parameter will be used. `VERSION` should not be
|
||||
* specified here.
|
||||
* @return {string|undefined} GetFeatureInfo URL.
|
||||
* @api
|
||||
*/
|
||||
getGetFeatureInfoUrl(coordinate, resolution, projection, params) {
|
||||
const projectionObj = getProjection(projection);
|
||||
const sourceProjectionObj = this.getProjection();
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projectionObj);
|
||||
}
|
||||
|
||||
const tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution);
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let tileResolution = tileGrid.getResolution(tileCoord[0]);
|
||||
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
|
||||
const gutter = this.gutter_;
|
||||
if (gutter !== 0) {
|
||||
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
|
||||
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
|
||||
}
|
||||
|
||||
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
|
||||
tileResolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, tileResolution);
|
||||
tileExtent = transformExtent(tileExtent, projectionObj, sourceProjectionObj);
|
||||
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
|
||||
}
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetFeatureInfo',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true,
|
||||
'QUERY_LAYERS': this.params_['LAYERS']
|
||||
};
|
||||
assign(baseParams, this.params_, params);
|
||||
|
||||
const x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
|
||||
const y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
|
||||
|
||||
baseParams[this.v13_ ? 'I' : 'X'] = x;
|
||||
baseParams[this.v13_ ? 'J' : 'Y'] = y;
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
1, sourceProjectionObj || projectionObj, baseParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getGutterInternal() {
|
||||
return this.gutter_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
getParams() {
|
||||
return this.params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/size~Size} tileSize Tile size.
|
||||
* @param {module:ol/extent~Extent} tileExtent Tile extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string|undefined} Request URL.
|
||||
* @private
|
||||
*/
|
||||
getRequestUrl_(tileCoord, tileSize, tileExtent, pixelRatio, projection, params) {
|
||||
|
||||
const urls = this.urls;
|
||||
if (!urls) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
params['WIDTH'] = tileSize[0];
|
||||
params['HEIGHT'] = tileSize[1];
|
||||
|
||||
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
|
||||
|
||||
if (!('STYLES' in this.params_)) {
|
||||
params['STYLES'] = '';
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
switch (this.serverType_) {
|
||||
case WMSServerType.GEOSERVER:
|
||||
const dpi = (90 * pixelRatio + 0.5) | 0;
|
||||
if ('FORMAT_OPTIONS' in params) {
|
||||
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
|
||||
} else {
|
||||
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
|
||||
}
|
||||
break;
|
||||
case WMSServerType.MAPSERVER:
|
||||
params['MAP_RESOLUTION'] = 90 * pixelRatio;
|
||||
break;
|
||||
case WMSServerType.CARMENTA_SERVER:
|
||||
case WMSServerType.QGIS:
|
||||
params['DPI'] = 90 * pixelRatio;
|
||||
break;
|
||||
default:
|
||||
assert(false, 52); // Unknown `serverType` configured
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const axisOrientation = projection.getAxisOrientation();
|
||||
const bbox = tileExtent;
|
||||
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
|
||||
let tmp;
|
||||
tmp = tileExtent[0];
|
||||
bbox[0] = tileExtent[1];
|
||||
bbox[1] = tmp;
|
||||
tmp = tileExtent[2];
|
||||
bbox[2] = tileExtent[3];
|
||||
bbox[3] = tmp;
|
||||
}
|
||||
params['BBOX'] = bbox.join(',');
|
||||
|
||||
let url;
|
||||
if (urls.length == 1) {
|
||||
url = urls[0];
|
||||
} else {
|
||||
const index = modulo(tileCoordHash(tileCoord), urls.length);
|
||||
url = urls[index];
|
||||
}
|
||||
return appendParams(url, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getTilePixelRatio(pixelRatio) {
|
||||
return (!this.hidpi_ || this.serverType_ === undefined) ? 1 :
|
||||
/** @type {number} */ (pixelRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
* @return {string} The key for the current params.
|
||||
*/
|
||||
this.gutter_ = options.gutter !== undefined ? options.gutter : 0;
|
||||
getKeyForParams_() {
|
||||
let i = 0;
|
||||
const res = [];
|
||||
for (const key in this.params_) {
|
||||
res[i++] = key + '-' + this.params_[key];
|
||||
}
|
||||
return res.join('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
fixedTileUrlFunction(tileCoord, pixelRatio, projection) {
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projection);
|
||||
}
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
|
||||
pixelRatio = 1;
|
||||
}
|
||||
|
||||
const tileResolution = tileGrid.getResolution(tileCoord[0]);
|
||||
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(
|
||||
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
const gutter = this.gutter_;
|
||||
if (gutter !== 0) {
|
||||
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
|
||||
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
|
||||
}
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetMap',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(baseParams, this.params_);
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, baseParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
updateParams(params) {
|
||||
assign(this.params_, params);
|
||||
this.updateV13_();
|
||||
this.setKey(this.getKeyForParams_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object}
|
||||
*/
|
||||
this.params_ = params;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.v13_ = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/source/WMSServerType|undefined}
|
||||
*/
|
||||
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/extent~Extent}
|
||||
*/
|
||||
this.tmpExtent_ = createEmpty();
|
||||
|
||||
this.updateV13_();
|
||||
this.setKey(this.getKeyForParams_());
|
||||
|
||||
};
|
||||
updateV13_() {
|
||||
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
|
||||
this.v13_ = compareVersions(version, '1.3') >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(TileWMS, TileImage);
|
||||
|
||||
|
||||
/**
|
||||
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
|
||||
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
|
||||
* constructed.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {module:ol/proj~ProjectionLike} projection Projection.
|
||||
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
|
||||
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
|
||||
* in the `LAYERS` parameter will be used. `VERSION` should not be
|
||||
* specified here.
|
||||
* @return {string|undefined} GetFeatureInfo URL.
|
||||
* @api
|
||||
*/
|
||||
TileWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
|
||||
const projectionObj = getProjection(projection);
|
||||
const sourceProjectionObj = this.getProjection();
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projectionObj);
|
||||
}
|
||||
|
||||
const tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution);
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let tileResolution = tileGrid.getResolution(tileCoord[0]);
|
||||
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
|
||||
const gutter = this.gutter_;
|
||||
if (gutter !== 0) {
|
||||
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
|
||||
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
|
||||
}
|
||||
|
||||
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
|
||||
tileResolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, tileResolution);
|
||||
tileExtent = transformExtent(tileExtent, projectionObj, sourceProjectionObj);
|
||||
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
|
||||
}
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetFeatureInfo',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true,
|
||||
'QUERY_LAYERS': this.params_['LAYERS']
|
||||
};
|
||||
assign(baseParams, this.params_, params);
|
||||
|
||||
const x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
|
||||
const y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
|
||||
|
||||
baseParams[this.v13_ ? 'I' : 'X'] = x;
|
||||
baseParams[this.v13_ ? 'J' : 'Y'] = y;
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
1, sourceProjectionObj || projectionObj, baseParams);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileWMS.prototype.getGutterInternal = function() {
|
||||
return this.gutter_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the user-provided params, i.e. those passed to the constructor through
|
||||
* the "params" option, and possibly updated using the updateParams method.
|
||||
* @return {Object} Params.
|
||||
* @api
|
||||
*/
|
||||
TileWMS.prototype.getParams = function() {
|
||||
return this.params_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
|
||||
* @param {module:ol/size~Size} tileSize Tile size.
|
||||
* @param {module:ol/extent~Extent} tileExtent Tile extent.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {module:ol/proj/Projection} projection Projection.
|
||||
* @param {Object} params Params.
|
||||
* @return {string|undefined} Request URL.
|
||||
* @private
|
||||
*/
|
||||
TileWMS.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, params) {
|
||||
|
||||
const urls = this.urls;
|
||||
if (!urls) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
params['WIDTH'] = tileSize[0];
|
||||
params['HEIGHT'] = tileSize[1];
|
||||
|
||||
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
|
||||
|
||||
if (!('STYLES' in this.params_)) {
|
||||
params['STYLES'] = '';
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
switch (this.serverType_) {
|
||||
case WMSServerType.GEOSERVER:
|
||||
const dpi = (90 * pixelRatio + 0.5) | 0;
|
||||
if ('FORMAT_OPTIONS' in params) {
|
||||
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
|
||||
} else {
|
||||
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
|
||||
}
|
||||
break;
|
||||
case WMSServerType.MAPSERVER:
|
||||
params['MAP_RESOLUTION'] = 90 * pixelRatio;
|
||||
break;
|
||||
case WMSServerType.CARMENTA_SERVER:
|
||||
case WMSServerType.QGIS:
|
||||
params['DPI'] = 90 * pixelRatio;
|
||||
break;
|
||||
default:
|
||||
assert(false, 52); // Unknown `serverType` configured
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const axisOrientation = projection.getAxisOrientation();
|
||||
const bbox = tileExtent;
|
||||
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
|
||||
let tmp;
|
||||
tmp = tileExtent[0];
|
||||
bbox[0] = tileExtent[1];
|
||||
bbox[1] = tmp;
|
||||
tmp = tileExtent[2];
|
||||
bbox[2] = tileExtent[3];
|
||||
bbox[3] = tmp;
|
||||
}
|
||||
params['BBOX'] = bbox.join(',');
|
||||
|
||||
let url;
|
||||
if (urls.length == 1) {
|
||||
url = urls[0];
|
||||
} else {
|
||||
const index = modulo(tileCoordHash(tileCoord), urls.length);
|
||||
url = urls[index];
|
||||
}
|
||||
return appendParams(url, params);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileWMS.prototype.getTilePixelRatio = function(pixelRatio) {
|
||||
return (!this.hidpi_ || this.serverType_ === undefined) ? 1 :
|
||||
/** @type {number} */ (pixelRatio);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {string} The key for the current params.
|
||||
*/
|
||||
TileWMS.prototype.getKeyForParams_ = function() {
|
||||
let i = 0;
|
||||
const res = [];
|
||||
for (const key in this.params_) {
|
||||
res[i++] = key + '-' + this.params_[key];
|
||||
}
|
||||
return res.join('/');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
TileWMS.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
|
||||
|
||||
let tileGrid = this.getTileGrid();
|
||||
if (!tileGrid) {
|
||||
tileGrid = this.getTileGridForProjection(projection);
|
||||
}
|
||||
|
||||
if (tileGrid.getResolutions().length <= tileCoord[0]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
|
||||
pixelRatio = 1;
|
||||
}
|
||||
|
||||
const tileResolution = tileGrid.getResolution(tileCoord[0]);
|
||||
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
|
||||
let tileSize = toSize(
|
||||
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
|
||||
|
||||
const gutter = this.gutter_;
|
||||
if (gutter !== 0) {
|
||||
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
|
||||
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
|
||||
}
|
||||
|
||||
if (pixelRatio != 1) {
|
||||
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
|
||||
}
|
||||
|
||||
const baseParams = {
|
||||
'SERVICE': 'WMS',
|
||||
'VERSION': DEFAULT_WMS_VERSION,
|
||||
'REQUEST': 'GetMap',
|
||||
'FORMAT': 'image/png',
|
||||
'TRANSPARENT': true
|
||||
};
|
||||
assign(baseParams, this.params_);
|
||||
|
||||
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
|
||||
pixelRatio, projection, baseParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the user-provided params.
|
||||
* @param {Object} params Params.
|
||||
* @api
|
||||
*/
|
||||
TileWMS.prototype.updateParams = function(params) {
|
||||
assign(this.params_, params);
|
||||
this.updateV13_();
|
||||
this.setKey(this.getKeyForParams_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
TileWMS.prototype.updateV13_ = function() {
|
||||
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
|
||||
this.v13_ = compareVersions(version, '1.3') >= 0;
|
||||
};
|
||||
export default TileWMS;
|
||||
|
||||
@@ -37,56 +37,173 @@ import {getKeyZXY} from '../tilecoord.js';
|
||||
* @extends {module:ol/source/Tile}
|
||||
* @param {module:ol/source/UrlTile~Options=} options Image tile options.
|
||||
*/
|
||||
const UrlTile = function(options) {
|
||||
class UrlTile {
|
||||
constructor(options) {
|
||||
|
||||
TileSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
extent: options.extent,
|
||||
opaque: options.opaque,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
tileGrid: options.tileGrid,
|
||||
tilePixelRatio: options.tilePixelRatio,
|
||||
wrapX: options.wrapX,
|
||||
transition: options.transition
|
||||
});
|
||||
TileSource.call(this, {
|
||||
attributions: options.attributions,
|
||||
cacheSize: options.cacheSize,
|
||||
extent: options.extent,
|
||||
opaque: options.opaque,
|
||||
projection: options.projection,
|
||||
state: options.state,
|
||||
tileGrid: options.tileGrid,
|
||||
tilePixelRatio: options.tilePixelRatio,
|
||||
wrapX: options.wrapX,
|
||||
transition: options.transition
|
||||
});
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~LoadFunction}
|
||||
*/
|
||||
this.tileLoadFunction = options.tileLoadFunction;
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~LoadFunction}
|
||||
*/
|
||||
this.tileLoadFunction = options.tileLoadFunction;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~UrlFunction}
|
||||
*/
|
||||
this.tileUrlFunction = this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) : nullTileUrlFunction;
|
||||
/**
|
||||
* @protected
|
||||
* @type {module:ol/Tile~UrlFunction}
|
||||
*/
|
||||
this.tileUrlFunction = this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) : nullTileUrlFunction;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array.<string>|null}
|
||||
*/
|
||||
this.urls = null;
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array.<string>|null}
|
||||
*/
|
||||
this.urls = null;
|
||||
|
||||
if (options.urls) {
|
||||
this.setUrls(options.urls);
|
||||
} else if (options.url) {
|
||||
this.setUrl(options.url);
|
||||
}
|
||||
if (options.tileUrlFunction) {
|
||||
this.setTileUrlFunction(options.tileUrlFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object.<number, boolean>}
|
||||
*/
|
||||
this.tileLoadingKeys_ = {};
|
||||
|
||||
if (options.urls) {
|
||||
this.setUrls(options.urls);
|
||||
} else if (options.url) {
|
||||
this.setUrl(options.url);
|
||||
}
|
||||
if (options.tileUrlFunction) {
|
||||
this.setTileUrlFunction(options.tileUrlFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object.<number, boolean>}
|
||||
* Return the tile load function of the source.
|
||||
* @return {module:ol/Tile~LoadFunction} TileLoadFunction
|
||||
* @api
|
||||
*/
|
||||
this.tileLoadingKeys_ = {};
|
||||
getTileLoadFunction() {
|
||||
return this.tileLoadFunction;
|
||||
}
|
||||
|
||||
};
|
||||
/**
|
||||
* Return the tile URL function of the source.
|
||||
* @return {module:ol/Tile~UrlFunction} TileUrlFunction
|
||||
* @api
|
||||
*/
|
||||
getTileUrlFunction() {
|
||||
return this.tileUrlFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URLs used for this source.
|
||||
* When a tileUrlFunction is used instead of url or urls,
|
||||
* null will be returned.
|
||||
* @return {!Array.<string>|null} URLs.
|
||||
* @api
|
||||
*/
|
||||
getUrls() {
|
||||
return this.urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tile change events.
|
||||
* @param {module:ol/events/Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
handleTileChange(event) {
|
||||
const tile = /** @type {module:ol/Tile} */ (event.target);
|
||||
const uid = getUid(tile);
|
||||
const tileState = tile.getState();
|
||||
let type;
|
||||
if (tileState == TileState.LOADING) {
|
||||
this.tileLoadingKeys_[uid] = true;
|
||||
type = TileEventType.TILELOADSTART;
|
||||
} else if (uid in this.tileLoadingKeys_) {
|
||||
delete this.tileLoadingKeys_[uid];
|
||||
type = tileState == TileState.ERROR ? TileEventType.TILELOADERROR :
|
||||
(tileState == TileState.LOADED || tileState == TileState.ABORT) ?
|
||||
TileEventType.TILELOADEND : undefined;
|
||||
}
|
||||
if (type != undefined) {
|
||||
this.dispatchEvent(new TileSourceEvent(type, tile));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tile load function of the source.
|
||||
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
||||
* @api
|
||||
*/
|
||||
setTileLoadFunction(tileLoadFunction) {
|
||||
this.tileCache.clear();
|
||||
this.tileLoadFunction = tileLoadFunction;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tile URL function of the source.
|
||||
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile URL function.
|
||||
* @param {string=} opt_key Optional new tile key for the source.
|
||||
* @api
|
||||
*/
|
||||
setTileUrlFunction(tileUrlFunction, opt_key) {
|
||||
this.tileUrlFunction = tileUrlFunction;
|
||||
this.tileCache.pruneExceptNewestZ();
|
||||
if (typeof opt_key !== 'undefined') {
|
||||
this.setKey(opt_key);
|
||||
} else {
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL to use for requests.
|
||||
* @param {string} url URL.
|
||||
* @api
|
||||
*/
|
||||
setUrl(url) {
|
||||
const urls = this.urls = expandUrl(url);
|
||||
this.setTileUrlFunction(this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) :
|
||||
createFromTemplates(urls, this.tileGrid), url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URLs to use for requests.
|
||||
* @param {Array.<string>} urls URLs.
|
||||
* @api
|
||||
*/
|
||||
setUrls(urls) {
|
||||
this.urls = urls;
|
||||
const key = urls.join('\n');
|
||||
this.setTileUrlFunction(this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) :
|
||||
createFromTemplates(urls, this.tileGrid), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
useTile(z, x, y) {
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
this.tileCache.get(tileCoordKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(UrlTile, TileSource);
|
||||
|
||||
@@ -97,126 +214,4 @@ inherits(UrlTile, TileSource);
|
||||
*/
|
||||
UrlTile.prototype.fixedTileUrlFunction;
|
||||
|
||||
/**
|
||||
* Return the tile load function of the source.
|
||||
* @return {module:ol/Tile~LoadFunction} TileLoadFunction
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.getTileLoadFunction = function() {
|
||||
return this.tileLoadFunction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the tile URL function of the source.
|
||||
* @return {module:ol/Tile~UrlFunction} TileUrlFunction
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.getTileUrlFunction = function() {
|
||||
return this.tileUrlFunction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the URLs used for this source.
|
||||
* When a tileUrlFunction is used instead of url or urls,
|
||||
* null will be returned.
|
||||
* @return {!Array.<string>|null} URLs.
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.getUrls = function() {
|
||||
return this.urls;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle tile change events.
|
||||
* @param {module:ol/events/Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
UrlTile.prototype.handleTileChange = function(event) {
|
||||
const tile = /** @type {module:ol/Tile} */ (event.target);
|
||||
const uid = getUid(tile);
|
||||
const tileState = tile.getState();
|
||||
let type;
|
||||
if (tileState == TileState.LOADING) {
|
||||
this.tileLoadingKeys_[uid] = true;
|
||||
type = TileEventType.TILELOADSTART;
|
||||
} else if (uid in this.tileLoadingKeys_) {
|
||||
delete this.tileLoadingKeys_[uid];
|
||||
type = tileState == TileState.ERROR ? TileEventType.TILELOADERROR :
|
||||
(tileState == TileState.LOADED || tileState == TileState.ABORT) ?
|
||||
TileEventType.TILELOADEND : undefined;
|
||||
}
|
||||
if (type != undefined) {
|
||||
this.dispatchEvent(new TileSourceEvent(type, tile));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the tile load function of the source.
|
||||
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.setTileLoadFunction = function(tileLoadFunction) {
|
||||
this.tileCache.clear();
|
||||
this.tileLoadFunction = tileLoadFunction;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the tile URL function of the source.
|
||||
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile URL function.
|
||||
* @param {string=} opt_key Optional new tile key for the source.
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction, opt_key) {
|
||||
this.tileUrlFunction = tileUrlFunction;
|
||||
this.tileCache.pruneExceptNewestZ();
|
||||
if (typeof opt_key !== 'undefined') {
|
||||
this.setKey(opt_key);
|
||||
} else {
|
||||
this.changed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the URL to use for requests.
|
||||
* @param {string} url URL.
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.setUrl = function(url) {
|
||||
const urls = this.urls = expandUrl(url);
|
||||
this.setTileUrlFunction(this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) :
|
||||
createFromTemplates(urls, this.tileGrid), url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the URLs to use for requests.
|
||||
* @param {Array.<string>} urls URLs.
|
||||
* @api
|
||||
*/
|
||||
UrlTile.prototype.setUrls = function(urls) {
|
||||
this.urls = urls;
|
||||
const key = urls.join('\n');
|
||||
this.setTileUrlFunction(this.fixedTileUrlFunction ?
|
||||
this.fixedTileUrlFunction.bind(this) :
|
||||
createFromTemplates(urls, this.tileGrid), key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
UrlTile.prototype.useTile = function(z, x, y) {
|
||||
const tileCoordKey = getKeyZXY(z, x, y);
|
||||
if (this.tileCache.containsKey(tileCoordKey)) {
|
||||
this.tileCache.get(tileCoordKey);
|
||||
}
|
||||
};
|
||||
export default UrlTile;
|
||||
|
||||
Reference in New Issue
Block a user