Using spatial index and combined filters
This should significantly speed up feature access. Needs unit tests.
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
goog.provide('ol.source.Vector');
|
goog.provide('ol.source.Vector');
|
||||||
|
|
||||||
goog.require('ol.Feature');
|
goog.require('ol.Feature');
|
||||||
goog.require('ol.filter.Filter');
|
goog.require('ol.filter.Extent');
|
||||||
goog.require('ol.filter.Geometry');
|
goog.require('ol.filter.Geometry');
|
||||||
|
goog.require('ol.filter.Logical');
|
||||||
goog.require('ol.geom.GeometryType');
|
goog.require('ol.geom.GeometryType');
|
||||||
goog.require('ol.source.Source');
|
goog.require('ol.source.Source');
|
||||||
|
goog.require('ol.structs.RTree');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -19,13 +21,18 @@ ol.source.FeatureCache = function() {
|
|||||||
*/
|
*/
|
||||||
this.idLookup_;
|
this.idLookup_;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Object.<ol.Feature>}
|
* @type {Object.<ol.Feature>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.geometryTypeIndex_;
|
this.geometryTypeIndex_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ol.structs.RTree}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.rTree_;
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -42,6 +49,8 @@ ol.source.FeatureCache.prototype.clear = function() {
|
|||||||
geometryTypeIndex[ol.geom.GeometryType[key]] = {};
|
geometryTypeIndex[ol.geom.GeometryType[key]] = {};
|
||||||
}
|
}
|
||||||
this.geometryTypeIndex_ = geometryTypeIndex;
|
this.geometryTypeIndex_ = geometryTypeIndex;
|
||||||
|
|
||||||
|
this.rTree_ = new ol.structs.RTree();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -55,17 +64,51 @@ ol.source.FeatureCache.prototype.add = function(feature) {
|
|||||||
|
|
||||||
this.idLookup_[id] = feature;
|
this.idLookup_[id] = feature;
|
||||||
|
|
||||||
// index by geometry type
|
// index by geometry type and bounding box
|
||||||
if (!goog.isNull(geometry)) {
|
if (!goog.isNull(geometry)) {
|
||||||
this.geometryTypeIndex_[geometry.getType()][id] = feature;
|
this.geometryTypeIndex_[geometry.getType()][id] = feature;
|
||||||
|
this.rTree_.put(geometry.getBounds(), feature);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Index by tile coord. To do this for real requires knowledge about
|
|
||||||
* the evaluated symbolizer literal for each feature. Initially, a pixel
|
|
||||||
* buffer could be provided.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.filter.Filter=} opt_filter Optional filter.
|
||||||
|
* @return {Object.<string, ol.Feature>} Object of features, keyed by id.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.source.FeatureCache.prototype.getFeaturesObject_ = function(opt_filter) {
|
||||||
|
var features;
|
||||||
|
if (!goog.isDef(opt_filter)) {
|
||||||
|
features = this.idLookup_;
|
||||||
|
} else {
|
||||||
|
if (opt_filter instanceof ol.filter.Logical) {
|
||||||
|
features = {};
|
||||||
|
var filters = opt_filter.getFilters(),
|
||||||
|
filterFeatures, key, or;
|
||||||
|
for (var i = filters.length - 1; i >= 0; --i) {
|
||||||
|
filterFeatures = this.getFeaturesObject_(filters[i]);
|
||||||
|
goog.object.extend(features, filterFeatures);
|
||||||
|
if (opt_filter.operator === ol.filter.LogicalOperator.AND) {
|
||||||
|
or = features;
|
||||||
|
features = {};
|
||||||
|
for (key in or) {
|
||||||
|
if (filterFeatures[key]) {
|
||||||
|
features[key] = or[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (opt_filter instanceof ol.filter.Geometry) {
|
||||||
|
features = this.geometryTypeIndex_[opt_filter.getType()];
|
||||||
|
} else if (opt_filter instanceof ol.filter.Extent) {
|
||||||
|
features = this.rTree_.find(opt_filter.getExtent());
|
||||||
|
} else {
|
||||||
|
// TODO: support other filter types
|
||||||
|
throw new Error('Filter type not supported: ' + opt_filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return features;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -74,22 +117,7 @@ ol.source.FeatureCache.prototype.add = function(feature) {
|
|||||||
* @return {Array.<ol.Feature>} Array of features.
|
* @return {Array.<ol.Feature>} Array of features.
|
||||||
*/
|
*/
|
||||||
ol.source.FeatureCache.prototype.getFeatures = function(opt_filter) {
|
ol.source.FeatureCache.prototype.getFeatures = function(opt_filter) {
|
||||||
var features;
|
return goog.object.getValues(this.getFeaturesObject_(opt_filter));
|
||||||
if (!goog.isDef(opt_filter)) {
|
|
||||||
features = new Array();
|
|
||||||
for (var id in this.idLookup_) {
|
|
||||||
features.push(this.idLookup_[id]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (opt_filter instanceof ol.filter.Geometry) {
|
|
||||||
features = this.getFeaturesByGeometryType_(
|
|
||||||
/** @type {ol.filter.Geometry} */ (opt_filter));
|
|
||||||
} else {
|
|
||||||
// TODO: support other filter types
|
|
||||||
throw new Error('Filter type not supported: ' + opt_filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user