Merge pull request #1089 from ahocevar/no-geometry-type-groups
No longer group features by geometry type
This commit is contained in:
@@ -6,13 +6,7 @@ goog.require('goog.asserts');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.expr');
|
||||
goog.require('ol.expr.Literal');
|
||||
goog.require('ol.expr.Logical');
|
||||
goog.require('ol.expr.LogicalOp');
|
||||
goog.require('ol.expr.functions');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.proj');
|
||||
goog.require('ol.source.Vector');
|
||||
@@ -34,12 +28,6 @@ ol.layer.FeatureCache = function() {
|
||||
*/
|
||||
this.idLookup_;
|
||||
|
||||
/**
|
||||
* @type {Object.<string, ol.Feature>}
|
||||
* @private
|
||||
*/
|
||||
this.geometryTypeIndex_;
|
||||
|
||||
/**
|
||||
* @type {ol.structs.RTree}
|
||||
* @private
|
||||
@@ -56,11 +44,6 @@ ol.layer.FeatureCache = function() {
|
||||
*/
|
||||
ol.layer.FeatureCache.prototype.clear = function() {
|
||||
this.idLookup_ = {};
|
||||
var geometryTypeIndex = {};
|
||||
for (var key in ol.geom.GeometryType) {
|
||||
geometryTypeIndex[ol.geom.GeometryType[key]] = {};
|
||||
}
|
||||
this.geometryTypeIndex_ = geometryTypeIndex;
|
||||
this.rTree_ = new ol.structs.RTree();
|
||||
};
|
||||
|
||||
@@ -75,99 +58,18 @@ ol.layer.FeatureCache.prototype.add = function(feature) {
|
||||
|
||||
this.idLookup_[id] = feature;
|
||||
|
||||
// index by geometry type and bounding box
|
||||
// index by bounding box
|
||||
if (!goog.isNull(geometry)) {
|
||||
var geometryType = geometry.getType();
|
||||
this.geometryTypeIndex_[geometryType][id] = feature;
|
||||
this.rTree_.insert(geometry.getBounds(),
|
||||
feature, geometryType);
|
||||
this.rTree_.insert(geometry.getBounds(), feature);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.expr.Expression=} opt_expr Expression for filtering.
|
||||
* @return {Object.<string, ol.Feature>} Object of features, keyed by id.
|
||||
*/
|
||||
ol.layer.FeatureCache.prototype.getFeaturesObject = function(opt_expr) {
|
||||
var features;
|
||||
if (!goog.isDef(opt_expr)) {
|
||||
features = this.idLookup_;
|
||||
} else {
|
||||
// check for geometryType or extent expression
|
||||
var name = ol.expr.isLibCall(opt_expr);
|
||||
if (name === ol.expr.functions.GEOMETRY_TYPE) {
|
||||
var args = /** @type {ol.expr.Call} */ (opt_expr).getArgs();
|
||||
goog.asserts.assert(args.length === 1);
|
||||
goog.asserts.assert(args[0] instanceof ol.expr.Literal);
|
||||
var type = /** @type {ol.expr.Literal } */ (args[0]).evaluate();
|
||||
goog.asserts.assertString(type);
|
||||
features = this.geometryTypeIndex_[type];
|
||||
} else if (name === ol.expr.functions.EXTENT) {
|
||||
var args = /** @type {ol.expr.Call} */ (opt_expr).getArgs();
|
||||
goog.asserts.assert(args.length === 4);
|
||||
for (var i = 0; i < 4; ++i) {
|
||||
goog.asserts.assert(args[i] instanceof ol.expr.Literal);
|
||||
}
|
||||
var extent = [
|
||||
/** @type {ol.expr.Literal} */ (args[0]).evaluate(),
|
||||
/** @type {ol.expr.Literal} */ (args[1]).evaluate(),
|
||||
/** @type {ol.expr.Literal} */ (args[2]).evaluate(),
|
||||
/** @type {ol.expr.Literal} */ (args[3]).evaluate()
|
||||
];
|
||||
features = this.rTree_.searchReturningObject(extent);
|
||||
} else {
|
||||
// not a call expression, check logical
|
||||
if (opt_expr instanceof ol.expr.Logical) {
|
||||
var op = /** @type {ol.expr.Logical} */ (opt_expr).getOperator();
|
||||
if (op === ol.expr.LogicalOp.AND) {
|
||||
var expressions = [opt_expr.getLeft(), opt_expr.getRight()];
|
||||
var expr, args, type, extent;
|
||||
for (var i = 0; i <= 1; ++i) {
|
||||
expr = expressions[i];
|
||||
name = ol.expr.isLibCall(expr);
|
||||
if (name === ol.expr.functions.GEOMETRY_TYPE) {
|
||||
args = /** @type {ol.expr.Call} */ (expr).getArgs();
|
||||
goog.asserts.assert(args.length === 1);
|
||||
goog.asserts.assert(args[0] instanceof ol.expr.Literal);
|
||||
type = /** @type {ol.expr.Literal } */ (args[0]).evaluate();
|
||||
goog.asserts.assertString(type);
|
||||
} else if (name === ol.expr.functions.EXTENT) {
|
||||
args = /** @type {ol.expr.Call} */ (expr).getArgs();
|
||||
goog.asserts.assert(args.length === 4);
|
||||
for (var j = 0; j < 4; ++j) {
|
||||
goog.asserts.assert(args[j] instanceof ol.expr.Literal);
|
||||
}
|
||||
extent = [[
|
||||
/** @type {ol.expr.Literal} */ (args[0]).evaluate(),
|
||||
/** @type {ol.expr.Literal} */ (args[1]).evaluate()
|
||||
], [
|
||||
/** @type {ol.expr.Literal} */ (args[2]).evaluate(),
|
||||
/** @type {ol.expr.Literal} */ (args[3]).evaluate()
|
||||
]];
|
||||
}
|
||||
}
|
||||
if (type && extent) {
|
||||
features = this.getFeaturesObjectForExtent(extent,
|
||||
/** @type {ol.geom.GeometryType} */ (type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!goog.isDef(features)) {
|
||||
// TODO: support fast lane for other filter types
|
||||
var candidates = this.idLookup_,
|
||||
feature;
|
||||
features = {};
|
||||
for (i in candidates) {
|
||||
feature = candidates[i];
|
||||
if (ol.expr.evaluateFeature(opt_expr, feature)) {
|
||||
features[i] = feature;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return features;
|
||||
ol.layer.FeatureCache.prototype.getFeaturesObject = function() {
|
||||
return this.idLookup_;
|
||||
};
|
||||
|
||||
|
||||
@@ -175,19 +77,10 @@ ol.layer.FeatureCache.prototype.getFeaturesObject = function(opt_expr) {
|
||||
* Get all features whose bounding box intersects the provided extent.
|
||||
*
|
||||
* @param {ol.Extent} extent Bounding extent.
|
||||
* @param {ol.geom.GeometryType=} opt_type Optional geometry type.
|
||||
* @return {Object.<string, ol.Feature>} Features.
|
||||
*/
|
||||
ol.layer.FeatureCache.prototype.getFeaturesObjectForExtent = function(extent,
|
||||
opt_type) {
|
||||
var features;
|
||||
if (goog.isDef(opt_type) &&
|
||||
goog.object.isEmpty(this.geometryTypeIndex_[opt_type])) {
|
||||
features = {};
|
||||
} else {
|
||||
features = this.rTree_.searchReturningObject(extent, opt_type);
|
||||
}
|
||||
return features;
|
||||
ol.layer.FeatureCache.prototype.getFeaturesObjectForExtent = function(extent) {
|
||||
return this.rTree_.searchReturningObject(extent);
|
||||
};
|
||||
|
||||
|
||||
@@ -228,10 +121,8 @@ ol.layer.FeatureCache.prototype.remove = function(feature) {
|
||||
|
||||
delete this.idLookup_[id];
|
||||
|
||||
// index by geometry type and bounding box
|
||||
// index by bounding box
|
||||
if (!goog.isNull(geometry)) {
|
||||
var geometryType = geometry.getType();
|
||||
delete this.geometryTypeIndex_[geometryType][id];
|
||||
this.rTree_.remove(geometry.getBounds(), feature);
|
||||
}
|
||||
};
|
||||
@@ -362,18 +253,17 @@ ol.layer.Vector.prototype.getStyle = function() {
|
||||
*
|
||||
* @param {ol.Extent} extent Bounding extent.
|
||||
* @param {ol.proj.Projection} projection Target projection.
|
||||
* @param {ol.geom.GeometryType=} opt_type Optional geometry type.
|
||||
* @param {Function=} opt_callback Callback to call when data is parsed.
|
||||
* @return {Object.<string, ol.Feature>} Features or null if source is loading
|
||||
* data for `extent`.
|
||||
*/
|
||||
ol.layer.Vector.prototype.getFeaturesObjectForExtent = function(extent,
|
||||
projection, opt_type, opt_callback) {
|
||||
projection, opt_callback) {
|
||||
var source = this.getSource();
|
||||
return source.prepareFeatures(this, extent, projection, opt_callback) ==
|
||||
ol.source.VectorLoadState.LOADING ?
|
||||
null :
|
||||
this.featureCache_.getFeaturesObjectForExtent(extent, opt_type);
|
||||
this.featureCache_.getFeaturesObjectForExtent(extent);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -101,21 +101,6 @@ ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {
|
||||
*/
|
||||
this.tileArchetype_ = null;
|
||||
|
||||
/**
|
||||
* Geometry types in rendering order.
|
||||
* TODO: these will go away shortly (in favor of one call per symbolizer type)
|
||||
* @private
|
||||
* @type {Array.<ol.geom.GeometryType>}
|
||||
*/
|
||||
this.geometryTypes_ = [
|
||||
ol.geom.GeometryType.POINT,
|
||||
ol.geom.GeometryType.MULTIPOINT,
|
||||
ol.geom.GeometryType.LINESTRING,
|
||||
ol.geom.GeometryType.MULTILINESTRING,
|
||||
ol.geom.GeometryType.POLYGON,
|
||||
ol.geom.GeometryType.MULTIPOLYGON
|
||||
];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
@@ -464,14 +449,10 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
||||
var tilesOnSketchCanvas = {};
|
||||
// TODO make gutter configurable?
|
||||
var tileGutter = 15 * tileResolution;
|
||||
var tile, tileCoord, key, x, y;
|
||||
// render features by geometry type
|
||||
var types = this.geometryTypes_,
|
||||
numTypes = types.length,
|
||||
deferred = false,
|
||||
dirty = false,
|
||||
i, type, tileExtent,
|
||||
groups, group, j, numGroups, featuresObject, tileHasFeatures;
|
||||
var tile, tileCoord, key, x, y, i, type;
|
||||
var deferred = false;
|
||||
var dirty = false;
|
||||
var tileExtent, groups, group, j, numGroups, featuresObject, tileHasFeatures;
|
||||
fetchTileData:
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
@@ -486,21 +467,15 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
||||
tileExtent[1] -= tileGutter;
|
||||
tileExtent[3] += tileGutter;
|
||||
tileHasFeatures = false;
|
||||
for (i = 0; i < numTypes; ++i) {
|
||||
type = types[i];
|
||||
if (!goog.isDef(featuresToRender[type])) {
|
||||
featuresToRender[type] = {};
|
||||
}
|
||||
featuresObject = layer.getFeaturesObjectForExtent(tileExtent,
|
||||
projection, type, this.requestMapRenderFrame_);
|
||||
if (goog.isNull(featuresObject)) {
|
||||
deferred = true;
|
||||
break fetchTileData;
|
||||
}
|
||||
tileHasFeatures = tileHasFeatures ||
|
||||
!goog.object.isEmpty(featuresObject);
|
||||
goog.object.extend(featuresToRender[type], featuresObject);
|
||||
featuresObject = layer.getFeaturesObjectForExtent(tileExtent,
|
||||
projection, this.requestMapRenderFrame_);
|
||||
if (goog.isNull(featuresObject)) {
|
||||
deferred = true;
|
||||
break fetchTileData;
|
||||
}
|
||||
tileHasFeatures = tileHasFeatures ||
|
||||
!goog.object.isEmpty(featuresObject);
|
||||
goog.object.extend(featuresToRender, featuresObject);
|
||||
if (tileHasFeatures) {
|
||||
tilesOnSketchCanvas[key] = tileCoord;
|
||||
}
|
||||
@@ -511,19 +486,15 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
||||
}
|
||||
this.dirty_ = dirty;
|
||||
|
||||
renderByGeometryType:
|
||||
for (type in featuresToRender) {
|
||||
groups = layer.groupFeaturesBySymbolizerLiteral(
|
||||
featuresToRender[type], tileResolution);
|
||||
numGroups = groups.length;
|
||||
for (j = 0; j < numGroups; ++j) {
|
||||
group = groups[j];
|
||||
deferred = sketchCanvasRenderer.renderFeaturesByGeometryType(
|
||||
/** @type {ol.geom.GeometryType} */ (type),
|
||||
group[0], group[1], group[2]);
|
||||
if (deferred) {
|
||||
break renderByGeometryType;
|
||||
}
|
||||
groups = layer.groupFeaturesBySymbolizerLiteral(featuresToRender,
|
||||
tileResolution);
|
||||
numGroups = groups.length;
|
||||
for (j = 0; j < numGroups; ++j) {
|
||||
group = groups[j];
|
||||
deferred = sketchCanvasRenderer.renderFeatures(group[0], group[1],
|
||||
group[2]);
|
||||
if (deferred) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,42 +114,21 @@ ol.renderer.canvas.Vector.prototype.getMaxSymbolSize = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.GeometryType} type Geometry type.
|
||||
* @param {Array.<ol.Feature>} features Array of features.
|
||||
* @param {ol.style.Literal} symbolizer Symbolizer.
|
||||
* @param {Array} data Additional data.
|
||||
* @return {boolean} true if deferred, false if rendered.
|
||||
*/
|
||||
ol.renderer.canvas.Vector.prototype.renderFeaturesByGeometryType =
|
||||
function(type, features, symbolizer, data) {
|
||||
ol.renderer.canvas.Vector.prototype.renderFeatures =
|
||||
function(features, symbolizer, data) {
|
||||
var deferred = false;
|
||||
if (!(symbolizer instanceof ol.style.TextLiteral)) {
|
||||
switch (type) {
|
||||
case ol.geom.GeometryType.POINT:
|
||||
case ol.geom.GeometryType.MULTIPOINT:
|
||||
goog.asserts.assert(symbolizer instanceof ol.style.PointLiteral,
|
||||
'Expected point symbolizer: ' + symbolizer);
|
||||
deferred = this.renderPointFeatures_(
|
||||
features, /** @type {ol.style.PointLiteral} */ (symbolizer));
|
||||
break;
|
||||
case ol.geom.GeometryType.LINESTRING:
|
||||
case ol.geom.GeometryType.MULTILINESTRING:
|
||||
goog.asserts.assert(symbolizer instanceof ol.style.LineLiteral,
|
||||
'Expected line symbolizer: ' + symbolizer);
|
||||
this.renderLineStringFeatures_(
|
||||
features, /** @type {ol.style.LineLiteral} */ (symbolizer));
|
||||
break;
|
||||
case ol.geom.GeometryType.POLYGON:
|
||||
case ol.geom.GeometryType.MULTIPOLYGON:
|
||||
goog.asserts.assert(symbolizer instanceof ol.style.PolygonLiteral,
|
||||
'Expected polygon symbolizer: ' + symbolizer);
|
||||
this.renderPolygonFeatures_(
|
||||
features, /** @type {ol.style.PolygonLiteral} */ (symbolizer));
|
||||
break;
|
||||
default:
|
||||
throw new Error('Rendering not implemented for geometry type: ' + type);
|
||||
}
|
||||
} else {
|
||||
if (symbolizer instanceof ol.style.PointLiteral) {
|
||||
deferred = this.renderPointFeatures_(features, symbolizer);
|
||||
} else if (symbolizer instanceof ol.style.LineLiteral) {
|
||||
this.renderLineStringFeatures_(features, symbolizer);
|
||||
} else if (symbolizer instanceof ol.style.PolygonLiteral) {
|
||||
this.renderPolygonFeatures_(features, symbolizer);
|
||||
} else if (symbolizer instanceof ol.style.TextLiteral) {
|
||||
this.renderText_(features, symbolizer, data);
|
||||
}
|
||||
return deferred;
|
||||
|
||||
Reference in New Issue
Block a user