Collect features before rendering to the sketch canvas

This avoids features being rendered multiple times when they
cross tile borders. Currently this makes the style-rules.html
example extremely slow. Fix for that to come in my next commit.
This commit is contained in:
ahocevar
2013-03-07 16:57:22 +01:00
parent f0039ee460
commit f4a16e7f57
2 changed files with 37 additions and 30 deletions

View File

@@ -76,9 +76,8 @@ ol.layer.FeatureCache.prototype.add = function(feature) {
/** /**
* @param {ol.filter.Filter=} opt_filter Optional filter. * @param {ol.filter.Filter=} opt_filter Optional filter.
* @return {Object.<string, ol.Feature>} Object of features, keyed by id. * @return {Object.<string, ol.Feature>} Object of features, keyed by id.
* @private
*/ */
ol.layer.FeatureCache.prototype.getFeaturesObject_ = function(opt_filter) { ol.layer.FeatureCache.prototype.getFeaturesObject = function(opt_filter) {
var i, features; var i, features;
if (!goog.isDef(opt_filter)) { if (!goog.isDef(opt_filter)) {
features = this.idLookup_; features = this.idLookup_;
@@ -123,15 +122,6 @@ ol.layer.FeatureCache.prototype.getFeaturesObject_ = function(opt_filter) {
}; };
/**
* @param {ol.filter.Filter=} opt_filter Optional filter.
* @return {Array.<ol.Feature>} Array of features.
*/
ol.layer.FeatureCache.prototype.getFeatures = function(opt_filter) {
return goog.object.getValues(this.getFeaturesObject_(opt_filter));
};
/** /**
* @param {ol.filter.Geometry} filter Geometry type filter. * @param {ol.filter.Geometry} filter Geometry type filter.
* @return {Array.<ol.Feature>} Array of features. * @return {Array.<ol.Feature>} Array of features.
@@ -209,12 +199,22 @@ ol.layer.Vector.prototype.getVectorSource = function() {
* @return {Array.<ol.Feature>} Array of features. * @return {Array.<ol.Feature>} Array of features.
*/ */
ol.layer.Vector.prototype.getFeatures = function(opt_filter) { ol.layer.Vector.prototype.getFeatures = function(opt_filter) {
return this.featureCache_.getFeatures(opt_filter); return goog.object.getValues(
this.featureCache_.getFeaturesObject(opt_filter));
}; };
/** /**
* @param {Array.<ol.Feature>} features Features. * @param {ol.filter.Filter=} opt_filter Optional filter.
* @return {Object.<string, ol.Feature>} Features.
*/
ol.layer.Vector.prototype.getFeaturesObject = function(opt_filter) {
return this.featureCache_.getFeaturesObject(opt_filter);
};
/**
* @param {Object.<string, ol.Feature>} features Features.
* @return {Array.<Array>} symbolizers for features. * @return {Array.<Array>} symbolizers for features.
*/ */
ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral = ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral =
@@ -222,9 +222,8 @@ ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral =
var uniqueLiterals = {}, var uniqueLiterals = {},
featuresBySymbolizer = [], featuresBySymbolizer = [],
style = this.style_, style = this.style_,
numFeatures = features.length,
i, j, l, feature, literals, numLiterals, literal, uniqueLiteral, key; i, j, l, feature, literals, numLiterals, literal, uniqueLiteral, key;
for (i = 0; i < numFeatures; ++i) { for (i in features) {
feature = features[i]; feature = features[i];
literals = feature.getSymbolizerLiterals(); literals = feature.getSymbolizerLiterals();
if (goog.isNull(literals)) { if (goog.isNull(literals)) {

View File

@@ -300,15 +300,16 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
finalCanvas.height = sketchSize.height; finalCanvas.height = sketchSize.height;
var finalContext = this.context_; var finalContext = this.context_;
var renderedFeatures = {}; var featuresToRender = {};
var tilesToRender = {}; var tilesToRender = {};
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, tileState, 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,
i, geomFilter, tileExtent, extentFilter, type, features, i, geomFilter, tileExtent, extentFilter, type,
groups, group, j, numGroups, deferred; groups, group, j, numGroups, deferred;
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) {
@@ -327,25 +328,32 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
for (i = 0; i < numFilters; ++i) { for (i = 0; i < numFilters; ++i) {
geomFilter = filters[i]; geomFilter = filters[i];
type = geomFilter.getType(); type = geomFilter.getType();
features = layer.getFeatures(new ol.filter.Logical( if (!goog.isDef(featuresToRender[type])) {
[geomFilter, extentFilter], ol.filter.LogicalOperator.AND)); featuresToRender[type] = {};
if (features.length) {
groups = layer.groupFeaturesBySymbolizerLiteral(features);
numGroups = groups.length;
for (j = 0; j < numGroups; ++j) {
group = groups[j];
deferred = sketchCanvasRenderer.renderFeaturesByGeometryType(
type, group[0], group[1]) || deferred;
}
} }
goog.object.extend(featuresToRender[type],
layer.getFeaturesObject(new ol.filter.Logical(
[geomFilter, extentFilter], ol.filter.LogicalOperator.AND)));
} }
if (!deferred) { tilesOnSketchCanvas[key] = tileCoord;
tilesToRender[key] = tileCoord;
}
} }
} }
} }
for (type in featuresToRender) {
groups = layer.groupFeaturesBySymbolizerLiteral(featuresToRender[type]);
numGroups = groups.length;
for (j = 0; j < numGroups; ++j) {
group = groups[j];
deferred = sketchCanvasRenderer.renderFeaturesByGeometryType(
/** @type {ol.geom.GeometryType} */ (type),
group[0], group[1]) || deferred;
}
if (!deferred) {
goog.object.extend(tilesToRender, tilesOnSketchCanvas);
}
}
this.dirty_ = true; this.dirty_ = true;
for (key in tilesToRender) { for (key in tilesToRender) {
tileCoord = tilesToRender[key]; tileCoord = tilesToRender[key];