From 3afd8b4242241c778e970f31eedb25919e65e94c Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 19 Jun 2013 18:15:22 +0200 Subject: [PATCH] Do not use a fixed tile grid for vector rendering Instead, we create a new tile grid whenever renderFrame is called, no animation is active, and the resolution is not in the tile grid already. This gives better rendering results because we get vector tiles at native resolutions. --- .../canvas/canvasvectorlayerrenderer.js | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 1a6b19ef44..4fb70a59b2 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -1,5 +1,6 @@ goog.provide('ol.renderer.canvas.VectorLayer'); +goog.require('goog.array'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); @@ -22,6 +23,12 @@ goog.require('ol.renderer.canvas.VectorRenderer'); goog.require('ol.tilegrid.TileGrid'); +/** + * @define {number} The lowest supported resolution value. + */ +ol.renderer.canvas.MIN_RESOLUTION = 0.14929107086948487; + + /** * @constructor @@ -303,16 +310,49 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame = resolution = view2DState.resolution, extent = frameState.extent, layer = this.getVectorLayer(), - tileGrid = this.tileGrid_; + tileGrid = this.tileGrid_, + resolutions, tileCoord, key, i; - if (goog.isNull(tileGrid)) { - // lazy tile grid creation to match the view projection - tileGrid = ol.tilegrid.createForProjection( - view2DState.projection, - 20, // should be no harm in going big here - ideally, it would be ∞ - [512, 512]); - this.tileGrid_ = tileGrid; + // lazy tile grid creation + if (!frameState.viewHints[ol.ViewHint.ANIMATING]) { + // Avoid rendering issues at very high zoom levels + var gridResolution = Math.max(resolution, + ol.renderer.canvas.MIN_RESOLUTION); + if (goog.isNull(tileGrid)) { + // start with the current resolution + resolutions = [gridResolution]; + } else if (!goog.array.contains(tileGrid.getResolutions(), + gridResolution)) { + // create a new tile grid, adding the current resolution, and update z + // tile coordinates in tile cache to match the new tile grid + var oldResolutions = tileGrid.getResolutions(); + resolutions = [gridResolution].concat(oldResolutions); + resolutions.sort(function(a, b) { return b - a; }); + var keys = this.tileCache_.getKeys(); + for (i = keys.length - 1; i >= 0; --i) { + key = keys[i]; + tileCoord = ol.TileCoord.createFromString(key); + tileCoord.z = goog.array.indexOf(resolutions, + oldResolutions[tileCoord.z]); + this.tileCache_.set(tileCoord.toString(), this.tileCache_.pop()); + } + } + if (goog.isDef(resolutions)) { + tileGrid = new ol.tilegrid.TileGrid({ + origin: [0, 0], + projection: view2DState.projection, + resolutions: resolutions, + tileSize: [512, 512] + }); + 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 var z = tileGrid.getZForResolution(resolution), @@ -399,7 +439,7 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame = var tilesOnSketchCanvas = {}; // TODO make gutter configurable? var tileGutter = 15 * tileResolution; - var tile, tileCoord, key, tileState, x, y; + var tile, x, y; // render features by geometry type var filters = this.geometryFilters_, numFilters = filters.length,