Store symbol sizes by tile
The reason for this change is that symbolSizes and maxSymbolSize on the instance will be wrong as soon as the resolution changes and cached tiles are used. It turned out that the approach used now has several advantages: smaller symbolSizes objects, no need to merge symbolSizes objects, and cache management for free (no risk of memory leaks). Note that the symbolSizes and maxSymbolSize for each tile are not strictly tile specific - they represent the rendering pass that created the tile. This has no negative side effects, and it has the advantage that there is not a single additional loop needed to create these structures.
This commit is contained in:
@@ -70,6 +70,10 @@ ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {
|
|||||||
this.sketchTransform_ = goog.vec.Mat4.createNumber();
|
this.sketchTransform_ = goog.vec.Mat4.createNumber();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tile cache entries are arrays. The first item in each array is the tile
|
||||||
|
* itself, the second are the symbol sizes, and the third is the maximum
|
||||||
|
* symbol size.
|
||||||
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {ol.TileCache}
|
* @type {ol.TileCache}
|
||||||
*/
|
*/
|
||||||
@@ -137,18 +141,6 @@ ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {
|
|||||||
*/
|
*/
|
||||||
this.tileGrid_ = null;
|
this.tileGrid_ = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Object.<number, Array.<number>>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.symbolSizes_ = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Array.<number>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.maxSymbolSize_ = [0, 0];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {function()}
|
* @type {function()}
|
||||||
@@ -173,8 +165,6 @@ ol.renderer.canvas.VectorLayer.prototype.expireTiles_ = function(opt_extent) {
|
|||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
}
|
}
|
||||||
this.tileCache_.clear();
|
this.tileCache_.clear();
|
||||||
this.symbolSizes_ = {};
|
|
||||||
this.maxSymbolSize_ = [0, 0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -213,17 +203,24 @@ ol.renderer.canvas.VectorLayer.prototype.getTransform = function() {
|
|||||||
ol.renderer.canvas.VectorLayer.prototype.getFeatureInfoForPixel =
|
ol.renderer.canvas.VectorLayer.prototype.getFeatureInfoForPixel =
|
||||||
function(pixel, success) {
|
function(pixel, success) {
|
||||||
var map = this.getMap();
|
var map = this.getMap();
|
||||||
|
var result = [];
|
||||||
|
|
||||||
var hw = this.maxSymbolSize_[0] / 2;
|
|
||||||
var hh = this.maxSymbolSize_[1] / 2;
|
|
||||||
var location = map.getCoordinateFromPixel(pixel);
|
var location = map.getCoordinateFromPixel(pixel);
|
||||||
|
var tileCoord = this.tileGrid_.getTileCoordForCoordAndResolution(
|
||||||
|
location, this.getMap().getView().getView2D().getResolution());
|
||||||
|
var key = tileCoord.toString();
|
||||||
|
if (this.tileCache_.containsKey(key)) {
|
||||||
|
var cachedTile = this.tileCache_.get(key);
|
||||||
|
var symbolSizes = cachedTile[1];
|
||||||
|
var maxSymbolSize = cachedTile[2];
|
||||||
|
var hw = maxSymbolSize[0] / 2;
|
||||||
|
var hh = maxSymbolSize[1] / 2;
|
||||||
var locationMin = [location[0] - hw, location[1] - hh];
|
var locationMin = [location[0] - hw, location[1] - hh];
|
||||||
var locationMax = [location[0] + hw, location[1] + hh];
|
var locationMax = [location[0] + hw, location[1] + hh];
|
||||||
var locationBbox = ol.extent.boundingExtent([locationMin, locationMax]);
|
var locationBbox = ol.extent.boundingExtent([locationMin, locationMax]);
|
||||||
var filter = new ol.filter.Extent(locationBbox);
|
var filter = new ol.filter.Extent(locationBbox);
|
||||||
var candidates = this.getLayer().getFeatures(filter);
|
var candidates = this.getLayer().getFeatures(filter);
|
||||||
|
|
||||||
var result = [];
|
|
||||||
var candidate, geom, type, symbolBounds, symbolSize, halfWidth, halfHeight,
|
var candidate, geom, type, symbolBounds, symbolSize, halfWidth, halfHeight,
|
||||||
coordinates, j;
|
coordinates, j;
|
||||||
for (var i = 0, ii = candidates.length; i < ii; ++i) {
|
for (var i = 0, ii = candidates.length; i < ii; ++i) {
|
||||||
@@ -234,7 +231,7 @@ ol.renderer.canvas.VectorLayer.prototype.getFeatureInfoForPixel =
|
|||||||
type === ol.geom.GeometryType.MULTIPOINT) {
|
type === ol.geom.GeometryType.MULTIPOINT) {
|
||||||
// For points, check if the pixel coordinate is inside the candidate's
|
// For points, check if the pixel coordinate is inside the candidate's
|
||||||
// symbol
|
// symbol
|
||||||
symbolSize = this.symbolSizes_[goog.getUid(candidate)];
|
symbolSize = symbolSizes[goog.getUid(candidate)];
|
||||||
halfWidth = symbolSize[0] / 2;
|
halfWidth = symbolSize[0] / 2;
|
||||||
halfHeight = symbolSize[1] / 2;
|
halfHeight = symbolSize[1] / 2;
|
||||||
symbolBounds = ol.extent.boundingExtent(
|
symbolBounds = ol.extent.boundingExtent(
|
||||||
@@ -253,11 +250,12 @@ ol.renderer.canvas.VectorLayer.prototype.getFeatureInfoForPixel =
|
|||||||
// For lines, check if the distance to the pixel location is
|
// For lines, check if the distance to the pixel location is
|
||||||
// within the rendered line width
|
// within the rendered line width
|
||||||
if (2 * geom.distanceFromCoordinate(location) <=
|
if (2 * geom.distanceFromCoordinate(location) <=
|
||||||
this.symbolSizes_[goog.getUid(candidate)][0]) {
|
symbolSizes[goog.getUid(candidate)][0]) {
|
||||||
result.push(candidate);
|
result.push(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
goog.global.setTimeout(function() { success(result); }, 0);
|
goog.global.setTimeout(function() { success(result); }, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -421,7 +419,6 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var renderedNew = false;
|
|
||||||
renderByGeometryType:
|
renderByGeometryType:
|
||||||
for (type in featuresToRender) {
|
for (type in featuresToRender) {
|
||||||
groups = layer.groupFeaturesBySymbolizerLiteral(featuresToRender[type]);
|
groups = layer.groupFeaturesBySymbolizerLiteral(featuresToRender[type]);
|
||||||
@@ -434,31 +431,26 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
|||||||
if (deferred) {
|
if (deferred) {
|
||||||
break renderByGeometryType;
|
break renderByGeometryType;
|
||||||
}
|
}
|
||||||
renderedNew = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderedNew) {
|
|
||||||
goog.object.extend(this.symbolSizes_,
|
|
||||||
sketchCanvasRenderer.getSymbolSizes());
|
|
||||||
this.maxSymbolSize_ = sketchCanvasRenderer.getMaxSymbolSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deferred) {
|
if (!deferred) {
|
||||||
goog.object.extend(tilesToRender, tilesOnSketchCanvas);
|
goog.object.extend(tilesToRender, tilesOnSketchCanvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var symbolSizes = sketchCanvasRenderer.getSymbolSizes(),
|
||||||
|
maxSymbolSize = sketchCanvasRenderer.getMaxSymbolSize();
|
||||||
for (key in tilesToRender) {
|
for (key in tilesToRender) {
|
||||||
tileCoord = tilesToRender[key];
|
tileCoord = tilesToRender[key];
|
||||||
if (this.tileCache_.containsKey(key)) {
|
if (this.tileCache_.containsKey(key)) {
|
||||||
tile = /** @type {HTMLCanvasElement} */ (this.tileCache_.get(key));
|
tile = /** @type {HTMLCanvasElement} */ (this.tileCache_.get(key)[0]);
|
||||||
} else {
|
} else {
|
||||||
tile = /** @type {HTMLCanvasElement} */
|
tile = /** @type {HTMLCanvasElement} */
|
||||||
(this.tileArchetype_.cloneNode(false));
|
(this.tileArchetype_.cloneNode(false));
|
||||||
tile.getContext('2d').drawImage(sketchCanvas,
|
tile.getContext('2d').drawImage(sketchCanvas,
|
||||||
(tileRange.minX - tileCoord.x) * tileSize.width,
|
(tileRange.minX - tileCoord.x) * tileSize.width,
|
||||||
(tileCoord.y - tileRange.maxY) * tileSize.height);
|
(tileCoord.y - tileRange.maxY) * tileSize.height);
|
||||||
this.tileCache_.set(key, tile);
|
this.tileCache_.set(key, [tile, symbolSizes, maxSymbolSize]);
|
||||||
}
|
}
|
||||||
finalContext.drawImage(tile,
|
finalContext.drawImage(tile,
|
||||||
tileSize.width * (tileCoord.x - tileRange.minX),
|
tileSize.width * (tileCoord.x - tileRange.minX),
|
||||||
|
|||||||
Reference in New Issue
Block a user