From 12bee3178e94841a6aadf2ff0ebebba5b48ec3ce Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 5 Mar 2013 12:41:44 +0100 Subject: [PATCH] Moving the feature management to the layer The source will be responsible for fetching vector data. --- examples/style-rules.js | 79 ++++--- examples/vector-layer.js | 11 +- src/ol/layer/vectorlayer.js | 192 ++++++++++++++++++ .../canvas/canvasvectorlayerrenderer.js | 5 +- src/ol/source/vectorsource.js | 185 ----------------- test/spec/ol/layer/vectorlayer.test.js | 101 +++++++++ test/spec/ol/source/vectorsource.test.js | 109 +--------- 7 files changed, 344 insertions(+), 338 deletions(-) diff --git a/examples/style-rules.js b/examples/style-rules.js index b2c0e1bd01..aa34ce8a00 100644 --- a/examples/style-rules.js +++ b/examples/style-rules.js @@ -15,11 +15,46 @@ goog.require('ol.style.Rule'); goog.require('ol.style.Style'); -var source = new ol.source.Vector({ - projection: ol.projection.getFromCode('EPSG:3857') +var style = new ol.style.Style({rules: [ + new ol.style.Rule({ + filter: new ol.filter.Filter(function(feature) { + return feature.get('where') == 'outer'; + }), + symbolizers: [ + new ol.style.Line({ + strokeStyle: new ol.Expression('color'), + strokeWidth: 4, + opacity: 1 + }) + ] + }), + new ol.style.Rule({ + filter: new ol.filter.Filter(function(feature) { + return feature.get('where') == 'inner'; + }), + symbolizers: [ + new ol.style.Line({ + strokeStyle: '#013', + strokeWidth: 4, + opacity: 1 + }), + new ol.style.Line({ + strokeStyle: new ol.Expression('color'), + strokeWidth: 2, + opacity: 1 + }) + ] + }) +]}); + +var vector = new ol.layer.Vector({ + style: style, + source: new ol.source.Vector({ + projection: ol.projection.getFromCode('EPSG:3857') + }) }); -source.addFeatures([ +vector.addFeatures([ new ol.Feature({ g: new ol.geom.LineString([[-10000000, -10000000], [10000000, 10000000]]), 'color': '#BADA55', @@ -52,44 +87,6 @@ source.addFeatures([ }) ]); -var style = new ol.style.Style({ - rules: [ - new ol.style.Rule({ - filter: new ol.filter.Filter(function(feature) { - return feature.get('where') == 'outer'; - }), - symbolizers: [ - new ol.style.Line({ - strokeStyle: new ol.Expression('color'), - strokeWidth: 4, - opacity: 1 - }) - ] - }), - new ol.style.Rule({ - filter: new ol.filter.Filter(function(feature) { - return feature.get('where') == 'inner'; - }), - symbolizers: [ - new ol.style.Line({ - strokeStyle: '#013', - strokeWidth: 4, - opacity: 1 - }), - new ol.style.Line({ - strokeStyle: new ol.Expression('color'), - strokeWidth: 2, - opacity: 1 - }) - ] - }) - ] -}); - -var vector = new ol.layer.Vector({ - source: source, - style: style -}); var map = new ol.Map({ layers: new ol.Collection([vector]), diff --git a/examples/vector-layer.js b/examples/vector-layer.js index 916dc6406b..e28f0d9cd6 100644 --- a/examples/vector-layer.js +++ b/examples/vector-layer.js @@ -17,11 +17,13 @@ var raster = new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }); -var source = new ol.source.Vector({ - projection: ol.projection.getFromCode('EPSG:3857') +var vector = new ol.layer.Vector({ + source: new ol.source.Vector({ + projection: ol.projection.getFromCode('EPSG:3857') + }) }); -source.addFeatures([ +vector.addFeatures([ new ol.Feature({ g: new ol.geom.LineString([[-10000000, -10000000], [10000000, 10000000]]) }), @@ -31,9 +33,6 @@ source.addFeatures([ new ol.Feature({g: new ol.geom.Point([-10000000, 5000000])}) ]); -var vector = new ol.layer.Vector({ - source: source -}); var map = new ol.Map({ layers: new ol.Collection([raster, vector]), diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 6703ec3e3c..77fde89ac2 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -3,10 +3,170 @@ goog.provide('ol.layer.Vector'); goog.require('ol.Feature'); goog.require('ol.layer.Layer'); goog.require('ol.source.Vector'); +goog.require('ol.structs.RTree'); goog.require('ol.style.Style'); +/** + * @constructor + */ +ol.layer.FeatureCache = function() { + + /** + * @type {Object.} + * @private + */ + this.idLookup_; + + /** + * @type {Object.} + * @private + */ + this.geometryTypeIndex_; + + /** + * @type {Object.} + * @private + */ + this.boundsByGeometryType_; + + this.clear(); + +}; + + +/** + * Clear the cache. + */ +ol.layer.FeatureCache.prototype.clear = function() { + this.idLookup_ = {}; + + var geometryTypeIndex = {}, + boundsByGeometryType = {}, + geometryType; + for (var key in ol.geom.GeometryType) { + geometryType = ol.geom.GeometryType[key]; + geometryTypeIndex[geometryType] = {}; + boundsByGeometryType[geometryType] = new ol.structs.RTree(); + } + this.geometryTypeIndex_ = geometryTypeIndex; + this.boundsByGeometryType_ = boundsByGeometryType; +}; + + +/** + * Add a feature to the cache. + * @param {ol.Feature} feature Feature to be cached. + */ +ol.layer.FeatureCache.prototype.add = function(feature) { + var id = goog.getUid(feature).toString(), + geometry = feature.getGeometry(); + + this.idLookup_[id] = feature; + + // index by geometry type and bounding box + if (!goog.isNull(geometry)) { + var geometryType = geometry.getType(); + this.geometryTypeIndex_[geometryType][id] = feature; + this.boundsByGeometryType_[geometryType].put(geometry.getBounds(), + feature); + } +}; + + +/** + * @param {ol.filter.Filter=} opt_filter Optional filter. + * @return {Object.} Object of features, keyed by id. + * @private + */ +ol.layer.FeatureCache.prototype.getFeaturesObject_ = function(opt_filter) { + var i, features; + if (!goog.isDef(opt_filter)) { + features = this.idLookup_; + } else { + if (opt_filter instanceof ol.filter.Geometry) { + features = this.geometryTypeIndex_[opt_filter.getType()]; + } else if (opt_filter instanceof ol.filter.Extent) { + var boundsByGeometryType = this.boundsByGeometryType_, + extent = opt_filter.getExtent(); + features = {}; + for (i in boundsByGeometryType) { + goog.object.extend(features, boundsByGeometryType[i].find(extent)); + } + } else if (opt_filter instanceof ol.filter.Logical && + opt_filter.operator === ol.filter.LogicalOperator.AND) { + var filters = opt_filter.getFilters(); + if (filters.length === 2) { + var filter, geometryFilter, extentFilter; + for (i = 0; i <= 1; ++i) { + filter = filters[i]; + if (filter instanceof ol.filter.Geometry) { + geometryFilter = filter; + } else if (filter instanceof ol.filter.Extent) { + extentFilter = filter; + } + } + if (extentFilter && geometryFilter) { + features = this.boundsByGeometryType_[geometryFilter.getType()] + .find(extentFilter.getExtent()); + } + } + } + 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 (opt_filter.applies(feature) === true) { + features[i] = feature; + } + } + } + } + return features; +}; + + +/** + * @param {ol.filter.Filter=} opt_filter Optional filter. + * @return {Array.} 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. + * @return {Array.} Array of features. + * @private + */ +ol.layer.FeatureCache.prototype.getFeaturesByGeometryType_ = function(filter) { + return goog.object.getValues(this.geometryTypeIndex_[filter.getType()]); +}; + + +/** + * Get features by ids. + * @param {Array.} ids Array of (internal) identifiers. + * @return {Array.} Array of features. + * @private + */ +ol.layer.FeatureCache.prototype.getFeaturesByIds_ = function(ids) { + var len = ids.length, + features = new Array(len), + i; + for (i = 0; i < len; ++i) { + features[i] = this.idLookup_[ids[i]]; + } + return features; +}; + + + /** * @constructor * @extends {ol.layer.Layer} @@ -21,10 +181,26 @@ ol.layer.Vector = function(layerOptions) { */ this.style_ = goog.isDef(layerOptions.style) ? layerOptions.style : null; + /** + * @type {ol.layer.FeatureCache} + * @private + */ + this.featureCache_ = new ol.layer.FeatureCache(); + }; goog.inherits(ol.layer.Vector, ol.layer.Layer); +/** + * @param {Array.} features Array of features. + */ +ol.layer.Vector.prototype.addFeatures = function(features) { + for (var i = 0, ii = features.length; i < ii; ++i) { + this.featureCache_.add(features[i]); + } +}; + + /** * @return {ol.source.Vector} Source. */ @@ -33,6 +209,15 @@ ol.layer.Vector.prototype.getVectorSource = function() { }; +/** + * @param {ol.filter.Filter=} opt_filter Optional filter. + * @return {Array.} Array of features. + */ +ol.layer.Vector.prototype.getFeatures = function(opt_filter) { + return this.featureCache_.getFeatures(opt_filter); +}; + + /** * @param {Array.} features Features. * @return {Array.} symbolizers for features. @@ -72,3 +257,10 @@ ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral = } return featuresBySymbolizer; }; + + +goog.require('ol.filter.Extent'); +goog.require('ol.filter.Geometry'); +goog.require('ol.filter.Logical'); +goog.require('ol.filter.LogicalOperator'); +goog.require('ol.geom.GeometryType'); diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index b4560e2e88..b3a0a191b6 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -167,11 +167,10 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame = resolution = view2DState.resolution, extent = frameState.extent, layer = this.getVectorLayer(), - source = layer.getVectorSource(), tileGrid = this.tileGrid_; if (goog.isNull(tileGrid)) { - // lazy tile source creation to match the view projection + // lazy tile grid creation to match the view projection tileGrid = ol.tilegrid.createForProjection( view2DState.projection, 22, // should be no harm in going big here - ideally, it would be ∞ @@ -282,7 +281,7 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame = for (i = 0; i < numFilters; ++i) { geomFilter = filters[i]; type = geomFilter.getType(); - features = source.getFeatures(new ol.filter.Logical( + features = layer.getFeatures(new ol.filter.Logical( [geomFilter, extentFilter], ol.filter.LogicalOperator.AND)); if (features.length) { groups = layer.groupFeaturesBySymbolizerLiteral(features); diff --git a/src/ol/source/vectorsource.js b/src/ol/source/vectorsource.js index 1dc6c0a0a1..60ff1f1228 100644 --- a/src/ol/source/vectorsource.js +++ b/src/ol/source/vectorsource.js @@ -11,166 +11,6 @@ goog.require('ol.filter.Logical'); goog.require('ol.filter.LogicalOperator'); goog.require('ol.geom.GeometryType'); goog.require('ol.source.Source'); -goog.require('ol.structs.RTree'); - - - -/** - * @constructor - */ -ol.source.FeatureCache = function() { - - /** - * @type {Object.} - * @private - */ - this.idLookup_; - - /** - * @type {Object.} - * @private - */ - this.geometryTypeIndex_; - - /** - * @type {Object.} - * @private - */ - this.boundsByGeometryType_; - - this.clear(); - -}; - - -/** - * Clear the cache. - */ -ol.source.FeatureCache.prototype.clear = function() { - this.idLookup_ = {}; - - var geometryTypeIndex = {}, - boundsByGeometryType = {}, - geometryType; - for (var key in ol.geom.GeometryType) { - geometryType = ol.geom.GeometryType[key]; - geometryTypeIndex[geometryType] = {}; - boundsByGeometryType[geometryType] = new ol.structs.RTree(); - } - this.geometryTypeIndex_ = geometryTypeIndex; - this.boundsByGeometryType_ = boundsByGeometryType; -}; - - -/** - * Add a feature to the cache. - * @param {ol.Feature} feature Feature to be cached. - */ -ol.source.FeatureCache.prototype.add = function(feature) { - var id = goog.getUid(feature).toString(), - geometry = feature.getGeometry(); - - this.idLookup_[id] = feature; - - // index by geometry type and bounding box - if (!goog.isNull(geometry)) { - var geometryType = geometry.getType(); - this.geometryTypeIndex_[geometryType][id] = feature; - this.boundsByGeometryType_[geometryType].put(geometry.getBounds(), - feature); - } -}; - - -/** - * @param {ol.filter.Filter=} opt_filter Optional filter. - * @return {Object.} Object of features, keyed by id. - * @private - */ -ol.source.FeatureCache.prototype.getFeaturesObject_ = function(opt_filter) { - var i, features; - if (!goog.isDef(opt_filter)) { - features = this.idLookup_; - } else { - if (opt_filter instanceof ol.filter.Geometry) { - features = this.geometryTypeIndex_[opt_filter.getType()]; - } else if (opt_filter instanceof ol.filter.Extent) { - var boundsByGeometryType = this.boundsByGeometryType_, - extent = opt_filter.getExtent(); - features = {}; - for (i in boundsByGeometryType) { - goog.object.extend(features, boundsByGeometryType[i].find(extent)); - } - } else if (opt_filter instanceof ol.filter.Logical && - opt_filter.operator === ol.filter.LogicalOperator.AND) { - var filters = opt_filter.getFilters(); - if (filters.length === 2) { - var filter, geometryFilter, extentFilter; - for (i = 0; i <= 1; ++i) { - filter = filters[i]; - if (filter instanceof ol.filter.Geometry) { - geometryFilter = filter; - } else if (filter instanceof ol.filter.Extent) { - extentFilter = filter; - } - } - if (extentFilter && geometryFilter) { - features = this.boundsByGeometryType_[geometryFilter.getType()] - .find(extentFilter.getExtent()); - } - } - } - 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 (opt_filter.applies(feature) === true) { - features[i] = feature; - } - } - } - } - return features; -}; - - -/** - * @param {ol.filter.Filter=} opt_filter Optional filter. - * @return {Array.} Array of features. - */ -ol.source.FeatureCache.prototype.getFeatures = function(opt_filter) { - return goog.object.getValues(this.getFeaturesObject_(opt_filter)); -}; - - -/** - * @param {ol.filter.Geometry} filter Geometry type filter. - * @return {Array.} Array of features. - * @private - */ -ol.source.FeatureCache.prototype.getFeaturesByGeometryType_ = function(filter) { - return goog.object.getValues(this.geometryTypeIndex_[filter.getType()]); -}; - - -/** - * Get features by ids. - * @param {Array.} ids Array of (internal) identifiers. - * @return {Array.} Array of features. - * @private - */ -ol.source.FeatureCache.prototype.getFeaturesByIds_ = function(ids) { - var len = ids.length, - features = new Array(len), - i; - for (i = 0; i < len; ++i) { - features[i] = this.idLookup_[ids[i]]; - } - return features; -}; /** @@ -195,30 +35,5 @@ ol.source.Vector = function(options) { projection: options.projection }); - /** - * @type {ol.source.FeatureCache} - * @private - */ - this.featureCache_ = new ol.source.FeatureCache(); - }; goog.inherits(ol.source.Vector, ol.source.Source); - - -/** - * @param {Array.} features Array of features. - */ -ol.source.Vector.prototype.addFeatures = function(features) { - for (var i = 0, ii = features.length; i < ii; ++i) { - this.featureCache_.add(features[i]); - } -}; - - -/** - * @param {ol.filter.Filter=} opt_filter Optional filter. - * @return {Array.} Array of features. - */ -ol.source.Vector.prototype.getFeatures = function(opt_filter) { - return this.featureCache_.getFeatures(opt_filter); -}; diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js index c08053419d..b6e5ff89ec 100644 --- a/test/spec/ol/layer/vectorlayer.test.js +++ b/test/spec/ol/layer/vectorlayer.test.js @@ -2,6 +2,99 @@ goog.provide('ol.test.layer.Vector'); describe('ol.layer.Vector', function() { + describe('#addFeatures()', function() { + + it('allows adding features', function() { + var layer = new ol.layer.Vector({ + new ol.source.Vector({}) + }); + layer.addFeatures([new ol.Feature(), new ol.Feature()]); + expect(layer.getFeatures().length).toEqual(2); + }); + }); + + describe('#getFeatures()', function() { + + var layer, features; + + beforeEach(function() { + features = [ + new ol.Feature({ + g: new ol.geom.Point([16.0, 48.0]) + }), + new ol.Feature({ + g: new ol.geom.Point([16.1, 48.1]) + }), + new ol.Feature({ + g: new ol.geom.Point([16.2, 48.2]) + }), + new ol.Feature({ + g: new ol.geom.Point([16.3, 48.3]) + }), + new ol.Feature({ + g: new ol.geom.LineString([[16.4, 48.4], [16.5, 48.5]]) + }), + new ol.Feature({ + g: new ol.geom.LineString([[16.6, 48.6], [16.7, 48.7]]) + }), + new ol.Feature({ + g: new ol.geom.LineString([[16.8, 48.8], [16.9, 48.9]]) + }), + new ol.Feature({ + g: new ol.geom.LineString([[17.0, 49.0], [17.1, 49.1]]) + }) + ]; + layer = new ol.layer.Vector({ + source: new ol.source.Vector({}) + }); + layer.addFeatures(features); + }); + + var geomFilter = new ol.filter.Geometry(ol.geom.GeometryType.LINESTRING); + var extentFilter = new ol.filter.Extent(new ol.Extent(16, 48, 16.3, 48.3)); + + it('can filter by geometry type using its GeometryType index', function() { + spyOn(geomFilter, 'applies'); + var lineStrings = layer.getFeatures(geomFilter); + expect(geomFilter.applies).not.toHaveBeenCalled(); + expect(lineStrings.length).toEqual(4); + expect(lineStrings).toContain(features[4]); + }); + + it('can filter by extent using its RTree', function() { + spyOn(extentFilter, 'applies'); + var subset = layer.getFeatures(extentFilter); + expect(extentFilter.applies).not.toHaveBeenCalled(); + expect(subset.length).toEqual(4); + expect(subset).not.toContain(features[7]); + }); + + it('can filter by extent and geometry type using its index', function() { + var filter1 = new ol.filter.Logical([geomFilter, extentFilter], + ol.filter.LogicalOperator.AND); + var filter2 = new ol.filter.Logical([extentFilter, geomFilter], + ol.filter.LogicalOperator.AND); + spyOn(filter1, 'applies'); + spyOn(filter2, 'applies'); + var subset1 = layer.getFeatures(filter1); + var subset2 = layer.getFeatures(filter2); + expect(filter1.applies).not.toHaveBeenCalled(); + expect(filter2.applies).not.toHaveBeenCalled(); + expect(subset1.length).toEqual(0); + expect(subset2.length).toEqual(0); + }); + + it('can handle query using the filter\'s applies function', function() { + var filter = new ol.filter.Logical([geomFilter, extentFilter], + ol.filter.LogicalOperator.OR); + spyOn(filter, 'applies').andCallThrough(); + var subset = layer.getFeatures(filter); + expect(filter.applies).toHaveBeenCalled(); + expect(subset.length).toEqual(8); + }); + + }); + describe('#groupFeaturesBySymbolizerLiteral()', function() { var layer = new ol.layer.Vector({ @@ -84,8 +177,16 @@ describe('ol.layer.Vector', function() { }); goog.require('ol.Expression'); +goog.require('ol.Extent'); goog.require('ol.Feature'); +goog.require('ol.Projection'); +goog.require('ol.filter.Extent'); +goog.require('ol.filter.Geometry'); +goog.require('ol.filter.Logical'); +goog.require('ol.filter.LogicalOperator'); +goog.require('ol.geom.GeometryType'); goog.require('ol.geom.LineString'); +goog.require('ol.geom.Point'); goog.require('ol.projection'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); diff --git a/test/spec/ol/source/vectorsource.test.js b/test/spec/ol/source/vectorsource.test.js index 37a6b46113..c2cbfdf028 100644 --- a/test/spec/ol/source/vectorsource.test.js +++ b/test/spec/ol/source/vectorsource.test.js @@ -3,112 +3,15 @@ goog.provide('ol.test.source.Vector'); describe('ol.source.Vector', function() { - var vectorSource; - - describe('#addFeatures()', function() { - - it('works', function() { - vectorSource = new ol.source.Vector({ - projection: ol.projection.getFromCode('EPSG:4326') - }); - vectorSource.addFeatures([new ol.Feature()]); - expect(vectorSource.getFeatures().length).toEqual(1); + describe('constructor', function() { + it('creates an instance', function() { + var source = new ol.source.Vector({}); + expect(source).toBeA(ol.source.Vector); + expect(source).toBeA(ol.source.Source); }); }); - describe('#getFeatures()', function() { - - var features; - - beforeEach(function() { - features = [ - new ol.Feature({ - g: new ol.geom.Point([16.0, 48.0]) - }), - new ol.Feature({ - g: new ol.geom.Point([16.1, 48.1]) - }), - new ol.Feature({ - g: new ol.geom.Point([16.2, 48.2]) - }), - new ol.Feature({ - g: new ol.geom.Point([16.3, 48.3]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[16.4, 48.4], [16.5, 48.5]]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[16.6, 48.6], [16.7, 48.7]]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[16.8, 48.8], [16.9, 48.9]]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[17.0, 49.0], [17.1, 49.1]]) - }) - ]; - vectorSource = new ol.source.Vector({ - projection: ol.projection.getFromCode('EPSG:4326') - }); - vectorSource.addFeatures(features); - }); - - var geomFilter = new ol.filter.Geometry(ol.geom.GeometryType.LINESTRING); - var extentFilter = new ol.filter.Extent(new ol.Extent(16, 48, 16.3, 48.3)); - - it('can filter by geometry type using its GeometryType index', function() { - spyOn(geomFilter, 'applies'); - var lineStrings = vectorSource.getFeatures(geomFilter); - expect(geomFilter.applies).not.toHaveBeenCalled(); - expect(lineStrings.length).toEqual(4); - expect(lineStrings).toContain(features[4]); - }); - - it('can filter by extent using its RTree', function() { - spyOn(extentFilter, 'applies'); - var subset = vectorSource.getFeatures(extentFilter); - expect(extentFilter.applies).not.toHaveBeenCalled(); - expect(subset.length).toEqual(4); - expect(subset).not.toContain(features[7]); - }); - - it('can filter by extent and geometry type using its index', function() { - var filter1 = new ol.filter.Logical([geomFilter, extentFilter], - ol.filter.LogicalOperator.AND); - var filter2 = new ol.filter.Logical([extentFilter, geomFilter], - ol.filter.LogicalOperator.AND); - spyOn(filter1, 'applies'); - spyOn(filter2, 'applies'); - var subset1 = vectorSource.getFeatures(filter1); - var subset2 = vectorSource.getFeatures(filter2); - expect(filter1.applies).not.toHaveBeenCalled(); - expect(filter2.applies).not.toHaveBeenCalled(); - expect(subset1.length).toEqual(0); - expect(subset2.length).toEqual(0); - }); - - it('can handle query using the filter\'s applies function', function() { - var filter = new ol.filter.Logical([geomFilter, extentFilter], - ol.filter.LogicalOperator.OR); - spyOn(filter, 'applies').andCallThrough(); - var subset = vectorSource.getFeatures(filter); - expect(filter.applies).toHaveBeenCalled(); - expect(subset.length).toEqual(8); - }); - - }); - }); -goog.require('ol.Extent'); -goog.require('ol.Feature'); -goog.require('ol.Projection'); -goog.require('ol.filter.Extent'); -goog.require('ol.filter.Geometry'); -goog.require('ol.filter.Logical'); -goog.require('ol.filter.LogicalOperator'); -goog.require('ol.geom.GeometryType'); -goog.require('ol.geom.Point'); -goog.require('ol.geom.LineString'); +goog.require('ol.source.Source'); goog.require('ol.source.Vector'); -goog.require('ol.projection');