Merge pull request #799 from ahocevar/dynamic-canvas-tilegrid

Do not use a fixed tile grid for vector rendering. r=@elemoine,@tschaub,@twpayne
This commit is contained in:
ahocevar
2013-06-23 11:15:50 -07:00
@@ -9,6 +9,7 @@ goog.require('goog.vec.Mat4');
goog.require('ol.Pixel'); goog.require('ol.Pixel');
goog.require('ol.TileCache'); goog.require('ol.TileCache');
goog.require('ol.TileCoord'); goog.require('ol.TileCoord');
goog.require('ol.TileRange');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.filter.Extent'); goog.require('ol.filter.Extent');
@@ -22,6 +23,17 @@ goog.require('ol.renderer.canvas.VectorRenderer');
goog.require('ol.tilegrid.TileGrid'); goog.require('ol.tilegrid.TileGrid');
/**
* Resolution at zoom level 21 in a web mercator default tiling scheme. This
* is a workaround for browser bugs that cause line segments to disappear when
* they get too long. TODO: Use line clipping as a better work around. See
* https://github.com/openlayers/ol3/issues/404.
*
* @define {number} The lowest supported resolution value.
*/
ol.renderer.canvas.MIN_RESOLUTION = 0.14929107086948487;
/** /**
* @constructor * @constructor
@@ -140,6 +152,15 @@ ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {
*/ */
this.tileGrid_ = null; this.tileGrid_ = null;
/**
* Tile range before the current animation or interaction. This is updated
* whenever the view is idle.
*
* @private
* @type {ol.TileRange}
*/
this.tileRange_ = null;
/** /**
* @private * @private
* @type {function()} * @type {function()}
@@ -219,8 +240,7 @@ ol.renderer.canvas.VectorLayer.prototype.getFeaturesForPixel =
var layer = this.getLayer(); var layer = this.getLayer();
var location = map.getCoordinateFromPixel(pixel); var location = map.getCoordinateFromPixel(pixel);
var tileCoord = this.tileGrid_.getTileCoordForCoordAndResolution( var tileCoord = this.tileGrid_.getTileCoordForCoordAndZ(location, 0);
location, this.getMap().getView().getView2D().getResolution());
var key = tileCoord.toString(); var key = tileCoord.toString();
if (this.tileCache_.containsKey(key)) { if (this.tileCache_.containsKey(key)) {
var cachedTile = this.tileCache_.get(key); var cachedTile = this.tileCache_.get(key);
@@ -301,28 +321,49 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
var view2DState = frameState.view2DState, var view2DState = frameState.view2DState,
resolution = view2DState.resolution, resolution = view2DState.resolution,
projection = view2DState.projection,
extent = frameState.extent, extent = frameState.extent,
layer = this.getVectorLayer(), layer = this.getVectorLayer(),
tileGrid = this.tileGrid_; tileGrid = this.tileGrid_,
tileSize = [512, 512],
idle = !frameState.viewHints[ol.ViewHint.ANIMATING] &&
!frameState.viewHints[ol.ViewHint.INTERACTING];
if (goog.isNull(tileGrid)) { // lazy tile grid creation
// lazy tile grid creation to match the view projection if (idle) {
tileGrid = ol.tilegrid.createForProjection( // avoid rendering issues for very high zoom levels
view2DState.projection, var gridResolution = Math.max(resolution,
20, // should be no harm in going big here - ideally, it would be ∞ ol.renderer.canvas.MIN_RESOLUTION /
[512, 512]); ol.METERS_PER_UNIT[projection.getUnits()]);
this.tileGrid_ = tileGrid; if (gridResolution !== this.renderedResolution_) {
tileGrid = new ol.tilegrid.TileGrid({
origin: [0, 0],
projection: projection,
resolutions: [gridResolution],
tileSize: tileSize
});
this.tileCache_.clear();
this.tileGrid_ = tileGrid;
}
} }
if (goog.isNull(tileGrid)) {
// We should only get here when the first call to renderFrame happens during
// an animation. Try again in the next renderFrame call.
return;
}
// set up transform for the layer canvas to be drawn to the map canvas // set up transform for the layer canvas to be drawn to the map canvas
var z = tileGrid.getZForResolution(resolution), var tileResolution = tileGrid.getResolution(0);
tileResolution = tileGrid.getResolution(z), if (idle) {
tileRange = tileGrid.getTileRangeForExtentAndResolution( this.tileRange_ = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution), extent, tileResolution);
tileRangeExtent = tileGrid.getTileRangeExtent(z, tileRange), }
tileSize = tileGrid.getTileSize(z), var transform = this.transform_,
sketchOrigin = ol.extent.getTopLeft(tileRangeExtent), tileRange = this.tileRange_,
transform = this.transform_; tileRangeExtent = tileGrid.getTileRangeExtent(0, tileRange),
sketchOrigin = ol.extent.getTopLeft(tileRangeExtent);
goog.vec.Mat4.makeIdentity(transform); goog.vec.Mat4.makeIdentity(transform);
goog.vec.Mat4.translate(transform, goog.vec.Mat4.translate(transform,
@@ -399,7 +440,7 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
var tilesOnSketchCanvas = {}; var tilesOnSketchCanvas = {};
// TODO make gutter configurable? // TODO make gutter configurable?
var tileGutter = 15 * tileResolution; var tileGutter = 15 * tileResolution;
var tile, tileCoord, key, tileState, x, y; var tile, tileCoord, key, x, y;
// render features by geometry type // render features by geometry type
var filters = this.geometryFilters_, var filters = this.geometryFilters_,
numFilters = filters.length, numFilters = filters.length,
@@ -409,11 +450,11 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
groups, group, j, numGroups, featuresObject, tileHasFeatures; groups, group, j, numGroups, featuresObject, tileHasFeatures;
for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoord = new ol.TileCoord(z, x, y); tileCoord = new ol.TileCoord(0, x, y);
key = tileCoord.toString(); key = tileCoord.toString();
if (this.tileCache_.containsKey(key)) { if (this.tileCache_.containsKey(key)) {
tilesToRender[key] = tileCoord; tilesToRender[key] = tileCoord;
} else if (!frameState.viewHints[ol.ViewHint.ANIMATING]) { } else if (idle) {
tileExtent = tileGrid.getTileCoordExtent(tileCoord); tileExtent = tileGrid.getTileCoordExtent(tileCoord);
tileExtent[0] -= tileGutter; tileExtent[0] -= tileGutter;
tileExtent[1] += tileGutter; tileExtent[1] += tileGutter;