diff --git a/src/ol/attribution.js b/src/ol/attribution.js
index acf59930e3..4b4c8886e2 100644
--- a/src/ol/attribution.js
+++ b/src/ol/attribution.js
@@ -1,17 +1,13 @@
goog.provide('ol.Attribution');
-goog.require('ol.CoverageArea');
-goog.require('ol.Projection');
-
/**
* @constructor
* @param {string} html HTML.
- * @param {Array.
=} opt_coverageAreas Coverage areas.
- * @param {ol.Projection=} opt_projection Projection.
+ * @param {Object.>=} opt_tileRanges Tile ranges.
*/
-ol.Attribution = function(html, opt_coverageAreas, opt_projection) {
+ol.Attribution = function(html, opt_tileRanges) {
/**
* @private
@@ -21,38 +17,40 @@ ol.Attribution = function(html, opt_coverageAreas, opt_projection) {
/**
* @private
- * @type {Array.}
+ * @type {Object.>}
*/
- this.coverageAreas_ = opt_coverageAreas || null;
+ this.tileRanges_ = opt_tileRanges || null;
- /**
- * @private
- * @type {ol.Projection}
- */
- this.projection_ = opt_projection || null;
-
-};
-
-
-/**
- * @return {Array.} Coverage areas.
- */
-ol.Attribution.prototype.getCoverageAreas = function() {
- return this.coverageAreas_;
};
/**
* @return {string} HTML.
*/
-ol.Attribution.prototype.getHtml = function() {
+ol.Attribution.prototype.getHTML = function() {
return this.html_;
};
/**
- * @return {ol.Projection} Projection.
+ * @param {Object.} tileRanges Tile ranges.
+ * @return {boolean} Intersects any tile range.
*/
-ol.Attribution.prototype.getProjection = function() {
- return this.projection_;
+ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges) {
+ if (goog.isNull(this.tileRanges_)) {
+ return true;
+ }
+ var i, tileRange, z;
+ for (z in tileRanges) {
+ if (!(z in this.tileRanges_)) {
+ continue;
+ }
+ tileRange = tileRanges[z];
+ for (i = 0; i < this.tileRanges_[z].length; ++i) {
+ if (this.tileRanges_[z][i].intersects(tileRange)) {
+ return true;
+ }
+ }
+ }
+ return false;
};
diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js
index 27f5a7f836..f7148722e8 100644
--- a/src/ol/control/attributioncontrol.js
+++ b/src/ol/control/attributioncontrol.js
@@ -1,24 +1,15 @@
-// FIXME handle rotation
// FIXME handle date line wrap
-// FIXME handle layer order
-// FIXME check clean-up code
-// FIXME works for View2D only
goog.provide('ol.control.Attribution');
+goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
-goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('goog.style');
-goog.require('ol.Collection');
-goog.require('ol.CoverageArea');
-goog.require('ol.TileCoverageArea');
-goog.require('ol.View2D');
-goog.require('ol.View2DProperty');
+goog.require('ol.MapEventType');
goog.require('ol.control.Control');
-goog.require('ol.layer.Layer');
@@ -36,324 +27,50 @@ ol.control.Attribution = function(attributionOptions) {
'class': 'ol-attribution'
}, this.ulElement_);
- /**
- * @private
- * @type {Object.}
- */
- this.layerVisibleChangeListenerKeys_ = {};
-
- /**
- * @private
- * @type {Object.}
- */
- this.attributionElements_ = {};
-
- /**
- * @private
- * @type {Object.>}
- */
- this.coverageAreass_ = {};
-
- /**
- * @private
- * @type {Array.}
- */
- this.mapListenerKeys_ = null;
-
- /**
- * @private
- * @type {Array.}
- */
- this.layersListenerKeys_ = null;
-
- /**
- * @private
- * @type {Array.}
- */
- this.viewListenerKeys_ = null;
-
goog.base(this, {
element: element,
map: attributionOptions.map,
target: attributionOptions.target
});
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.renderedVisible_ = true;
+
+ /**
+ * @private
+ * @type {Object.}
+ */
+ this.attributionElements_ = {};
+
+ /**
+ * @private
+ * @type {Object.}
+ */
+ this.attributionElementRenderedVisible_ = {};
+
+ /**
+ * @private
+ * @type {Array.}
+ */
+ this.listenerKeys_ = null;
+
};
goog.inherits(ol.control.Attribution, ol.control.Control);
/**
- * @param {ol.layer.Layer} layer Layer.
- * @protected
+ * @param {ol.MapEvent} mapEvent Map event.
*/
-ol.control.Attribution.prototype.addLayer = function(layer) {
-
- var layerKey = goog.getUid(layer);
-
- this.layerVisibleChangeListenerKeys_[layerKey] = goog.events.listen(
- layer, ol.Object.getChangedEventType(ol.layer.LayerProperty.VISIBLE),
- this.handleLayerVisibleChanged, false, this);
-
- if (layer.getSource().isReady()) {
- this.createAttributionElementsForLayer_(layer);
+ol.control.Attribution.prototype.handleMapPostrender = function(mapEvent) {
+ var frameState = mapEvent.frameState;
+ if (goog.isNull(frameState)) {
+ this.updateElement_(null);
} else {
- goog.events.listenOnce(layer, goog.events.EventType.LOAD,
- this.handleLayerLoad, false, this);
+ this.updateElement_(frameState.tileUsage);
}
-
-};
-
-
-/**
- * @param {ol.layer.Layer} layer Layer.
- * @private
- */
-ol.control.Attribution.prototype.createAttributionElementsForLayer_ =
- function(layer) {
-
- var source = layer.getSource();
- var attributions = source.getAttributions();
- if (goog.isNull(attributions)) {
- return;
- }
-
- var map = this.getMap();
- var mapIsDef = map.isDef();
- var layerVisible = layer.getVisible();
-
- var attributionVisibilities;
- if (mapIsDef && layerVisible) {
- var mapSize = /** @type {ol.Size} */ (map.getSize());
- // FIXME works for View2D only
- var view = map.getView();
- goog.asserts.assert(view instanceof ol.View2D);
- var mapExtent = view.getExtent(mapSize);
- var mapProjection = /** @type {ol.Projection} */ (view.getProjection());
- var mapResolution = /** @type {number} */ (view.getResolution());
- attributionVisibilities = this.getLayerAttributionVisiblities_(
- layer, mapExtent, mapResolution, mapProjection);
- } else {
- attributionVisibilities = null;
- }
-
- goog.array.forEach(attributions, function(attribution) {
-
- var attributionKey = goog.getUid(attribution);
-
- var attributionElement = goog.dom.createElement(goog.dom.TagName.LI);
- attributionElement.innerHTML = attribution.getHtml();
-
- if (!mapIsDef ||
- !layerVisible ||
- goog.isNull(attributionVisibilities) ||
- !attributionVisibilities[attributionKey]) {
- if (goog.style.isElementShown(attributionElement)) {
- goog.style.showElement(attributionElement, false);
- }
- }
-
- goog.dom.appendChild(this.ulElement_, attributionElement);
-
- this.attributionElements_[attributionKey] = attributionElement;
-
- }, this);
-
-};
-
-
-/**
- * @param {ol.layer.Layer} layer Layer.
- * @param {ol.Extent} mapExtent View extent.
- * @param {number} mapResolution View resolution.
- * @param {ol.Projection} mapProjection Map projection.
- * @return {Object.} Attribution visibilities.
- * @private
- */
-ol.control.Attribution.prototype.getLayerAttributionVisiblities_ =
- function(layer, mapExtent, mapResolution, mapProjection) {
-
- var source = layer.getSource();
- var attributions = source.getAttributions();
-
- if (goog.isNull(attributions)) {
- return null;
- }
-
- var mapZ;
- if (source instanceof ol.source.TileSource) {
- var tileSource = /** @type {ol.source.TileSource} */ (source);
- var tileGrid = tileSource.getTileGrid();
- mapZ = tileGrid.getZForResolution(mapResolution);
- }
-
- var attributionVisibilities = {};
- goog.array.forEach(attributions, function(attribution) {
-
- var attributionKey = goog.getUid(attribution);
-
- var attributionVisible = true;
-
- var coverageAreas;
- if (attributionKey in this.coverageAreass_) {
- coverageAreas = this.coverageAreass_[attributionKey];
- } else {
- var attributionProjection = attribution.getProjection();
- coverageAreas = attribution.getCoverageAreas();
- if (!goog.isNull(coverageAreas) &&
- !ol.Projection.equivalent(attributionProjection, mapProjection)) {
- var transformFn = ol.Projection.getTransform(
- attributionProjection, mapProjection);
- if (transformFn !== ol.Projection.cloneTransform) {
- coverageAreas = goog.array.map(coverageAreas, function(coverageArea) {
- return coverageArea.transform(transformFn);
- });
- }
- }
- this.coverageAreass_[attributionKey] = coverageAreas;
- }
-
- if (!goog.isNull(coverageAreas)) {
- if (source instanceof ol.source.TileSource) {
- attributionVisible = goog.array.some(
- coverageAreas,
- function(coverageArea, index) {
- return coverageArea.intersectsExtentAndZ(mapExtent, mapZ);
- });
- } else {
- attributionVisible = goog.array.some(
- coverageAreas,
- function(coverageArea) {
- return coverageArea.intersectsExtentAndResolution(
- mapExtent, mapResolution);
- });
- }
- }
-
- attributionVisibilities[attributionKey] = attributionVisible;
-
- }, this);
-
- return attributionVisibilities;
-
-};
-
-
-/**
- * @param {goog.events.Event} event Event.
- */
-ol.control.Attribution.prototype.handleLayerLoad = function(event) {
- var layer = /** @type {ol.layer.Layer} */ (event.target);
- this.createAttributionElementsForLayer_(layer);
-};
-
-
-/**
- * @param {goog.events.Event} event Event.
- * @protected
- */
-ol.control.Attribution.prototype.handleLayerVisibleChanged = function(event) {
- var layer = /** @type {ol.layer.Layer} */ (event.target);
- this.updateLayerAttributionsVisibility_(layer);
-
-};
-
-
-/**
- * @param {ol.CollectionEvent} collectionEvent Collection event.
- * @protected
- */
-ol.control.Attribution.prototype.handleLayersAdd = function(collectionEvent) {
- var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem);
- this.addLayer(layer);
-};
-
-
-/**
- * @param {ol.CollectionEvent} collectionEvent Collection event.
- * @protected
- */
-ol.control.Attribution.prototype.handleLayersRemove =
- function(collectionEvent) {
- var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem);
- this.removeLayer(layer);
-};
-
-
-/**
- * @protected
- */
-ol.control.Attribution.prototype.handleMapViewChanged = function() {
- if (!goog.isNull(this.viewListenerKeys_)) {
- goog.array.forEach(this.viewListenerKeys_, goog.events.unlistenByKey);
- this.viewListenerKeys_ = null;
- }
- var map = this.getMap();
- goog.asserts.assert(!goog.isNull(map));
- var view = map.getView();
- if (!goog.isNull(view)) {
- // FIXME works for View2D only
- goog.asserts.assert(view instanceof ol.View2D);
- this.viewListenerKeys_ = [
- goog.events.listen(
- view, ol.Object.getChangedEventType(ol.View2DProperty.CENTER),
- this.updateAttributions, false, this),
- goog.events.listen(
- view, ol.Object.getChangedEventType(ol.View2DProperty.RESOLUTION),
- this.updateAttributions, false, this)
- ];
- }
-};
-
-
-/**
- * @protected
- */
-ol.control.Attribution.prototype.handleMapLayersChanged = function() {
- if (!goog.isNull(this.layersListenerKeys_)) {
- goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
- this.layersListenerKeys_ = null;
- }
- goog.object.forEach(this.attributionElements_, function(attributionElement) {
- goog.dom.removeNode(attributionElement);
- }, this);
- this.attributionElements_ = {};
- this.coverageAreass_ = {};
- var map = this.getMap();
- var layers = map.getLayers();
- if (goog.isDefAndNotNull(layers)) {
- layers.forEach(this.addLayer, this);
- this.layersListenerKeys_ = [
- goog.events.listen(layers, ol.CollectionEventType.ADD,
- this.handleLayersAdd, false, this),
- goog.events.listen(layers, ol.CollectionEventType.REMOVE,
- this.handleLayersRemove, false, this)
- ];
- }
-};
-
-
-/**
- * @param {ol.layer.Layer} layer Layer.
- * @protected
- */
-ol.control.Attribution.prototype.removeLayer = function(layer) {
-
- var layerKey = goog.getUid(layer);
-
- goog.events.unlistenByKey(this.layerVisibleChangeListenerKeys_[layerKey]);
- delete this.layerVisibleChangeListenerKeys_[layerKey];
-
- goog.array.forEach(
- layer.getSource().getAttributions(),
- function(attribution) {
- var attributionKey = goog.getUid(attribution);
- delete this.coverageAreass_[attributionKey];
- var attributionElement = this.attributionElements_[attributionKey];
- goog.dom.removeNode(attributionElement);
- delete this.attributionElements_[attributionKey];
- },
- this);
-
};
@@ -361,79 +78,116 @@ ol.control.Attribution.prototype.removeLayer = function(layer) {
* @inheritDoc
*/
ol.control.Attribution.prototype.setMap = function(map) {
- if (!goog.isNull(this.mapListenerKeys_)) {
- goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
+ if (!goog.isNull(this.listenerKeys_)) {
+ goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey);
+ this.listenerKeys_ = null;
}
- this.mapListenerKeys_ = null;
goog.base(this, 'setMap', map);
if (!goog.isNull(map)) {
- this.mapListenerKeys_ = [
- goog.events.listen(
- map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS),
- this.handleMapLayersChanged, false, this),
- goog.events.listen(
- map, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
- this.updateAttributions, false, this),
- goog.events.listen(
- map, ol.Object.getChangedEventType(ol.MapProperty.VIEW),
- this.updateAttributions, false, this)
+ this.listenerKeys_ = [
+ goog.events.listen(map, ol.MapEventType.POSTRENDER,
+ this.handleMapPostrender, false, this)
];
- this.handleMapViewChanged();
- this.handleMapLayersChanged();
}
};
/**
- * @protected
- */
-ol.control.Attribution.prototype.updateAttributions = function() {
-
- var map = this.getMap();
- var layers = map.getLayers();
- layers.forEach(function(layer) {
- this.updateLayerAttributionsVisibility_(layer);
- }, this);
-
-};
-
-
-/**
- * @param {ol.layer.Layer} layer Layer.
* @private
+ * @param {?Object.>} tileUsage Tile
+ * usage.
*/
-ol.control.Attribution.prototype.updateLayerAttributionsVisibility_ =
- function(layer) {
+ol.control.Attribution.prototype.updateElement_ = function(tileUsage) {
+
+ if (goog.isNull(tileUsage)) {
+ if (this.renderedVisible_) {
+ goog.style.showElement(this.element, false);
+ this.renderedVisible_ = false;
+ }
+ return;
+ }
+
var map = this.getMap();
- if (map.isDef() && layer.getVisible()) {
- var mapSize = /** @type {ol.Size} */ (map.getSize());
- var view = map.getView();
- // FIXME works for View2D only
- goog.asserts.assert(view instanceof ol.View2D);
- var mapExtent = view.getExtent(mapSize);
- var mapProjection = /** @type {ol.Projection} */ (view.getProjection());
- var mapResolution = /** @type {number} */ (view.getResolution());
- var attributionVisibilities = this.getLayerAttributionVisiblities_(
- layer, mapExtent, mapResolution, mapProjection);
- goog.object.forEach(
- attributionVisibilities,
- function(attributionVisible, attributionKey) {
- var attributionElement = this.attributionElements_[attributionKey];
- if (goog.style.isElementShown(attributionElement) !=
- attributionVisible) {
- goog.style.showElement(attributionElement, attributionVisible);
- }
- },
- this);
- } else {
- var source = layer.getSource();
- var attributions = source.getAttributions();
- if (!goog.isNull(attributions)) {
- goog.array.forEach(attributions, function(attribution) {
- var attributionKey = goog.getUid(attribution);
- var attributionElement = this.attributionElements_[attributionKey];
- goog.style.showElement(attributionElement, false);
- }, this);
+
+ /** @type {Object.} */
+ var attributionsToRemove = {};
+ /** @type {Object.} */
+ var tileSources = {};
+ var layers = map.getLayers();
+ if (goog.isDef(layers)) {
+ layers.forEach(function(layer) {
+ var source = layer.getSource();
+ if (source instanceof ol.source.TileSource) {
+ tileSources[goog.getUid(source).toString()] = source;
+ }
+ var attributions = source.getAttributions();
+ if (!goog.isNull(attributions)) {
+ var attribution, i;
+ for (i = 0; i < attributions.length; ++i) {
+ attribution = attributions[i];
+ attributionKey = goog.getUid(attribution).toString();
+ attributionsToRemove[attributionKey] = true;
+ }
+ }
+ });
+ }
+
+ /** @type {Object.} */
+ var attributions = {};
+ var i, tileRanges, tileSource, tileSourceAttribution,
+ tileSourceAttributionKey, tileSourceAttributions, tileSourceKey, z;
+ for (tileSourceKey in tileUsage) {
+ goog.asserts.assert(tileSourceKey in tileSources);
+ tileSource = tileSources[tileSourceKey];
+ tileSourceAttributions = tileSource.getAttributions();
+ if (goog.isNull(tileSourceAttributions)) {
+ continue;
+ }
+ tileRanges = tileUsage[tileSourceKey];
+ for (i = 0; i < tileSourceAttributions.length; ++i) {
+ tileSourceAttribution = tileSourceAttributions[i];
+ tileSourceAttributionKey = goog.getUid(tileSourceAttribution).toString();
+ if (tileSourceAttributionKey in attributions) {
+ continue;
+ }
+ if (tileSourceAttribution.intersectsAnyTileRange(tileRanges)) {
+ attributions[tileSourceAttributionKey] = tileSourceAttribution;
+ }
}
}
+
+ /** @type {Array.} */
+ var attributionKeys =
+ goog.array.map(goog.object.getKeys(attributions), Number);
+ goog.array.sort(attributionKeys);
+ var attributionElement, attributionKey;
+ for (i = 0; i < attributionKeys.length; ++i) {
+ attributionKey = attributionKeys[i].toString();
+ if (attributionKey in this.attributionElements_) {
+ if (!this.attributionElementRenderedVisible_[attributionKey]) {
+ goog.style.showElement(this.attributionElements_[attributionKey], true);
+ this.attributionElementRenderedVisible_[attributionKey] = true;
+ }
+ } else {
+ attributionElement = goog.dom.createElement(goog.dom.TagName.LI);
+ attributionElement.innerHTML = attributions[attributionKey].getHTML();
+ goog.dom.appendChild(this.ulElement_, attributionElement);
+ this.attributionElements_[attributionKey] = attributionElement;
+ this.attributionElementRenderedVisible_[attributionKey] = true;
+ }
+ delete attributionsToRemove[attributionKey];
+ }
+
+ for (attributionKey in attributionsToRemove) {
+ goog.dom.removeNode(this.attributionElements_[attributionKey]);
+ delete this.attributionElements_[attributionKey];
+ delete this.attributionElementRenderedVisible_[attributionKey];
+ }
+
+ var renderVisible = !goog.array.isEmpty(attributionKeys);
+ if (this.renderedVisible_ != renderVisible) {
+ goog.style.showElement(this.element, renderVisible);
+ this.renderedVisible_ = renderVisible;
+ }
+
};
diff --git a/src/ol/coveragearea.js b/src/ol/coveragearea.js
deleted file mode 100644
index 55fe982796..0000000000
--- a/src/ol/coveragearea.js
+++ /dev/null
@@ -1,55 +0,0 @@
-goog.provide('ol.CoverageArea');
-
-goog.require('ol.Extent');
-
-
-
-/**
- * Represents a rectangular area.
- *
- * @constructor
- * @param {ol.Extent} extent Extent.
- */
-ol.CoverageArea = function(extent) {
-
- /**
- * @type {ol.Extent}
- */
- this.extent = extent;
-
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @return {boolean} Intersects.
- */
-ol.CoverageArea.prototype.intersectsExtent = function(extent) {
- return this.extent.intersects(extent);
-};
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {number} resolution Resolution.
- * @return {boolean} Intersects.
- */
-ol.CoverageArea.prototype.intersectsExtentAndResolution = goog.abstractMethod;
-
-
-/**
- * @param {ol.Extent} extent Extent.
- * @param {number} z Z.
- * @return {boolean} Intersects.
- */
-ol.CoverageArea.prototype.intersectsExtentAndZ = goog.abstractMethod;
-
-
-/**
- * @param {ol.TransformFunction} transformFn Transform.
- * @return {ol.CoverageArea} Transformed coverage area.
- */
-ol.CoverageArea.prototype.transform = function(transformFn) {
- var extent = this.extent.transform(transformFn);
- return new ol.CoverageArea(extent);
-};
diff --git a/src/ol/framestate.js b/src/ol/framestate.js
index d84f4de831..574fefe20f 100644
--- a/src/ol/framestate.js
+++ b/src/ol/framestate.js
@@ -10,6 +10,7 @@ goog.require('ol.Coordinate');
goog.require('ol.Extent');
goog.require('ol.Size');
goog.require('ol.TileQueue');
+goog.require('ol.TileRange');
goog.require('ol.View2DState');
goog.require('ol.layer.LayerState');
@@ -25,6 +26,7 @@ goog.require('ol.layer.LayerState');
* postRenderFunctions: Array.,
* size: ol.Size,
* tileQueue: ol.TileQueue,
+ * tileUsage: Object.>,
* time: number,
* view2DState: ol.View2DState,
* viewHints: Array.}}
diff --git a/src/ol/map.js b/src/ol/map.js
index f82253eeaf..383529adeb 100644
--- a/src/ol/map.js
+++ b/src/ol/map.js
@@ -617,6 +617,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
postRenderFunctions: [],
size: size,
tileQueue: this.tileQueue_,
+ tileUsage: {},
view2DState: view2DState,
viewHints: viewHints,
time: time
diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js
index cdbfb92305..f80ca05e04 100644
--- a/src/ol/renderer/dom/domtilelayerrenderer.js
+++ b/src/ol/renderer/dom/domtilelayerrenderer.js
@@ -89,6 +89,21 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
frameState.extent, tileResolution);
+ // FIXME should also consider interim tiles
+ var tileUsage = frameState.tileUsage;
+ var tileSourceKey = goog.getUid(tileSource).toString();
+ var zKey = z.toString();
+ if (tileSourceKey in tileUsage) {
+ if (z in tileUsage[tileSourceKey]) {
+ tileUsage[tileSourceKey][zKey].extend(tileRange);
+ } else {
+ tileUsage[tileSourceKey][zKey] = tileRange;
+ }
+ } else {
+ tileUsage[tileSourceKey] = {};
+ tileUsage[tileSourceKey][zKey] = tileRange;
+ }
+
/** @type {Object.>} */
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js
index 43f83838fd..e9ddb277b3 100644
--- a/src/ol/renderer/webgl/webgltilelayerrenderer.js
+++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js
@@ -276,6 +276,21 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
frameState.extent, tileResolution);
+ // FIXME should also consider interim tiles
+ var tileUsage = frameState.tileUsage;
+ var tileSourceKey = goog.getUid(tileSource).toString();
+ var zKey = z.toString();
+ if (tileSourceKey in tileUsage) {
+ if (z in tileUsage[tileSourceKey]) {
+ tileUsage[tileSourceKey][zKey].extend(tileRange);
+ } else {
+ tileUsage[tileSourceKey][zKey] = tileRange;
+ }
+ } else {
+ tileUsage[tileSourceKey] = {};
+ tileUsage[tileSourceKey][zKey] = tileRange;
+ }
+
var framebufferExtent;
if (!goog.isNull(this.renderedTileRange_) &&
diff --git a/src/ol/source/bingmapssource.js b/src/ol/source/bingmapssource.js
index 7693cb81d9..a700ba09d2 100644
--- a/src/ol/source/bingmapssource.js
+++ b/src/ol/source/bingmapssource.js
@@ -5,7 +5,7 @@ goog.require('goog.Uri');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.net.Jsonp');
-goog.require('ol.TileCoverageArea');
+goog.require('ol.TileRange');
goog.require('ol.source.ImageTileSource');
goog.require('ol.tilegrid.XYZ');
@@ -118,21 +118,35 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
};
})));
- var projection = ol.Projection.getFromCode('EPSG:4326');
+ var transform = ol.Projection.getTransform(
+ ol.Projection.getFromCode('EPSG:4326'), this.getProjection());
var attributions = goog.array.map(
resource.imageryProviders,
function(imageryProvider) {
var html = imageryProvider.attribution;
- var coverageAreas = goog.array.map(
+ /** @type {Object.>} */
+ var tileRanges = {};
+ goog.array.forEach(
imageryProvider.coverageAreas,
function(coverageArea) {
- var bbox = coverageArea.bbox;
- var extent = new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]);
var minZ = coverageArea.zoomMin;
var maxZ = coverageArea.zoomMax;
- return new ol.TileCoverageArea(tileGrid, extent, minZ, maxZ);
+ var bbox = coverageArea.bbox;
+ var epsg4326Extent =
+ new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]);
+ var extent = epsg4326Extent.transform(transform);
+ var tileRange, z, zKey;
+ for (z = minZ; z <= maxZ; ++z) {
+ zKey = z.toString();
+ tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
+ if (zKey in tileRanges) {
+ tileRanges[zKey].push(tileRange);
+ } else {
+ tileRanges[zKey] = [tileRange];
+ }
+ }
});
- return new ol.Attribution(html, coverageAreas, projection);
+ return new ol.Attribution(html, tileRanges);
});
this.setAttributions(attributions);
diff --git a/src/ol/source/tilejsonsource.js b/src/ol/source/tilejsonsource.js
index 81eacaf7a4..af306b0d26 100644
--- a/src/ol/source/tilejsonsource.js
+++ b/src/ol/source/tilejsonsource.js
@@ -14,7 +14,6 @@ goog.require('goog.events.EventType');
goog.require('goog.net.jsloader');
goog.require('goog.string');
goog.require('ol.Projection');
-goog.require('ol.TileCoverageArea');
goog.require('ol.TileUrlFunction');
goog.require('ol.source.ImageTileSource');
goog.require('ol.tilegrid.XYZ');
@@ -98,17 +97,17 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function() {
if (goog.isDef(tileJSON.scheme)) {
goog.asserts.assert(tileJSON.scheme == 'xyz');
}
- var minzoom = tileJSON.minzoom || 0;
- goog.asserts.assert(minzoom === 0); // FIXME
- var maxzoom = tileJSON.maxzoom || 22;
+ var minZoom = tileJSON.minzoom || 0;
+ goog.asserts.assert(minZoom === 0); // FIXME
+ var maxZoom = tileJSON.maxzoom || 22;
var tileGrid = new ol.tilegrid.XYZ({
- maxZoom: maxzoom
+ maxZoom: maxZoom
});
this.tileGrid = tileGrid;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
- if (tileCoord.z < minzoom || maxzoom < tileCoord.z) {
+ if (tileCoord.z < minZoom || maxZoom < tileCoord.z) {
return null;
}
var n = 1 << tileCoord.z;
@@ -129,13 +128,18 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function() {
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
if (goog.isDef(tileJSON.attribution)) {
- var coverageAreas = [
- new ol.TileCoverageArea(tileGrid, epsg4326Extent, minzoom, maxzoom)
- ];
- var coverageAreaProjection = epsg4326Projection;
+ var attributionExtent = goog.isNull(extent) ?
+ epsg4326Projection.getExtent() : extent;
+ /** @type {Object.>} */
+ var tileRanges = {};
+ var z, zKey;
+ for (z = minZoom; z <= maxZoom; ++z) {
+ zKey = z.toString();
+ tileRanges[zKey] =
+ [tileGrid.getTileRangeForExtentAndZ(attributionExtent, z)];
+ }
this.setAttributions([
- new ol.Attribution(
- tileJSON.attribution, coverageAreas, coverageAreaProjection)
+ new ol.Attribution(tileJSON.attribution, tileRanges)
]);
}
diff --git a/src/ol/tilecoveragearea.js b/src/ol/tilecoveragearea.js
deleted file mode 100644
index f09e1d1797..0000000000
--- a/src/ol/tilecoveragearea.js
+++ /dev/null
@@ -1,69 +0,0 @@
-goog.provide('ol.TileCoverageArea');
-
-goog.require('ol.CoverageArea');
-goog.require('ol.Extent');
-goog.require('ol.tilegrid.TileGrid');
-
-
-
-/**
- * @constructor
- * @extends {ol.CoverageArea}
- * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
- * @param {ol.Extent} extent Extent.
- * @param {number} minZ Minimum Z.
- * @param {number} maxZ Maximum Z.
- */
-ol.TileCoverageArea = function(tileGrid, extent, minZ, maxZ) {
-
- goog.base(this, extent);
-
- /**
- * @private
- * @type {ol.tilegrid.TileGrid}
- */
- this.tileGrid_ = tileGrid;
-
- /**
- * @private
- * @type {number}
- */
- this.minZ_ = minZ;
-
- /**
- * @private
- * @type {number}
- */
- this.maxZ_ = maxZ;
-
-};
-goog.inherits(ol.TileCoverageArea, ol.CoverageArea);
-
-
-/**
- * @inheritDoc
- */
-ol.TileCoverageArea.prototype.intersectsExtentAndResolution =
- function(extent, resolution) {
- var z = this.tileGrid_.getZForResolution(resolution);
- return this.intersectsExtentAndZ(extent, z);
-};
-
-
-/**
- * @inheritDoc
- */
-ol.TileCoverageArea.prototype.intersectsExtentAndZ = function(extent, z) {
- return this.minZ_ <= z && z <= this.maxZ_ && this.intersectsExtent(extent);
-};
-
-
-/**
- * @param {ol.TransformFunction} transformFn Transform.
- * @return {ol.TileCoverageArea} Transformed tile coverage area.
- */
-ol.TileCoverageArea.prototype.transform = function(transformFn) {
- var extent = this.extent.transform(transformFn);
- return new ol.TileCoverageArea(
- this.tileGrid_, extent, this.minZ_, this.maxZ_);
-};