From 0f4a5c09af06ff9a0c97f81e9ab06e0e14427e2d Mon Sep 17 00:00:00 2001 From: ahocevar Date: Mon, 20 May 2013 17:47:04 +0200 Subject: [PATCH] Porting tests from http://github.com/imbcmdth/RTree/ Also fixes some issues that were revealed by the new tests. --- src/ol/structs/rtree.js | 12 +-- test/spec/ol/structs/rtree.test.js | 114 +++++++++++++++++++++-------- 2 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/ol/structs/rtree.js b/src/ol/structs/rtree.js index 17d27f8fc6..e43bef5e61 100644 --- a/src/ol/structs/rtree.js +++ b/src/ol/structs/rtree.js @@ -120,7 +120,7 @@ ol.structs.RTree = function(opt_width) { /** @type {ol.structs.RTreeNode} */ var workingObject = /** @type {ol.structs.RTreeNode} */ - ({extent: goog.array.concat(rect), target: obj}); + ({extent: goog.array.concat(rect.extent), target: obj}); countStack.push(root.nodes.length); hitStack.push(root); @@ -521,19 +521,20 @@ ol.structs.RTree = function(opt_width) { * @this {ol.structs.RTree} */ this.find = function(extent, opt_type) { - var rect = ({extent: extent}); + var rect = /** @type {ol.structs.RTreeNode} */ ({extent: extent}); return searchSubtree.apply(this, [rect, false, {}, rootTree, opt_type]); }; /** * Non-recursive function that deletes a specific region. * - * @param {ol.structs.RTreeNode} rect Rectangle. + * @param {ol.Extent} extent Extent. * @param {Object=} opt_obj Object. * @return {Array} Result. * @this {ol.structs.RTree} */ - this.remove = function(rect, opt_obj) { + this.remove = function(extent, opt_obj) { + arguments[0] = /** @type {ol.structs.RTreeNode} */ ({extent: extent}); switch (arguments.length) { case 1: arguments[1] = false; // opt_obj == false for conditionals @@ -563,7 +564,8 @@ ol.structs.RTree = function(opt_width) { * @param {string=} opt_type Optional type to store along with the object. */ this.put = function(extent, obj, opt_type) { - var node = ({extent: extent, leaf: obj}); + var node = /** @type {ol.structs.RTreeNode} */ + ({extent: extent, leaf: obj}); if (goog.isDef(opt_type)) { node.type = opt_type; } diff --git a/test/spec/ol/structs/rtree.test.js b/test/spec/ol/structs/rtree.test.js index f8fbb83e84..e5ee9baef6 100644 --- a/test/spec/ol/structs/rtree.test.js +++ b/test/spec/ol/structs/rtree.test.js @@ -3,20 +3,94 @@ goog.provide('ol.test.structs.RTree'); describe('ol.structs.RTree', function() { - describe('put and find', function() { - var rTree = new ol.structs.RTree(); - rTree.put([0, 1, 0, 1], 1); - rTree.put([1, 4, 1, 4], 2); - rTree.put([2, 3, 2, 3], 3); - rTree.put([-5, -4, -5, -4], 4); - rTree.put([-4, -1, -4, -1], 5); - rTree.put([-3, -2, -3, -2], 6); + var rTree = new ol.structs.RTree(); - it('stores items', function() { - expect(goog.object.getCount(rTree.find([-100, 100, -100, 100]))).to.be(6); + describe('creation', function() { + it('can insert 1k objects', function() { + var i = 1000; + while (i > 0) { + var bounds = new Array(4); + bounds[0] = Math.random() * 10000; + bounds[1] = bounds[0] + Math.random() * 500; + bounds[2] = Math.random() * 10000; + bounds[3] = bounds[2] + Math.random() * 500; + rTree.put(bounds, 'JUST A TEST OBJECT!_' + i); + i--; + } + expect(goog.object.getCount(rTree.find([0, 10600, 0, 10600]))) + .to.be(1000); }); + it('can insert 1k more objects', function() { + var i = 1000; + while (i > 0) { + var bounds = new Array(4); + bounds[0] = Math.random() * 10000; + bounds[1] = bounds[0] + Math.random() * 500; + bounds[2] = Math.random() * 10000; + bounds[3] = bounds[2] + Math.random() * 500; + rTree.put(bounds, 'JUST A TEST OBJECT!_' + i); + i--; + } + expect(goog.object.getCount(rTree.find([0, 10600, 0, 10600]))) + .to.be(2000); + }); + }); + + describe('search', function() { + it('can perform 1k out-of-bounds searches', function() { + var i = 1000; + var len = 0; + while (i > 0) { + var bounds = new Array(4); + bounds[0] = -(Math.random() * 10000 + 501); + bounds[1] = bounds[0] + Math.random() * 500; + bounds[2] = -(Math.random() * 10000 + 501); + bounds[3] = bounds[2] + Math.random() * 500; + len += goog.object.getCount(rTree.find(bounds)); + i--; + } + expect(len).to.be(0); + }); + it('can perform 1k in-bounds searches', function() { + var i = 1000; + var len = 0; + while (i > 0) { + var bounds = new Array(4); + bounds[0] = -Math.random() * 10000 + 501; + bounds[1] = bounds[0] + Math.random() * 500; + bounds[2] = -Math.random() * 10000 + 501; + bounds[3] = bounds[2] + Math.random() * 500; + len += goog.object.getCount(rTree.find(bounds)); + i--; + } + expect(len).not.to.be(0); + }); + }); + + describe('deletion', function() { + var len = 0; + it('can delete half the RTree', function() { + var bounds = [5000, 10500, 0, 10500]; + len += rTree.remove(bounds).length; + expect(len).to.not.be(0); + }); + it('can delete the other half of the RTree', function() { + var bounds = [0, 5000, 0, 10500]; + len += rTree.remove(bounds).length; + expect(len).to.be(2000); + }); + }); + + describe('result plausibility', function() { it('filters by rectangle', function() { + rTree.put([0, 1, 0, 1], 1); + rTree.put([1, 4, 1, 4], 2); + rTree.put([2, 3, 2, 3], 3); + rTree.put([-5, -4, -5, -4], 4); + rTree.put([-4, -1, -4, -1], 5); + rTree.put([-3, -2, -3, -2], 6); + var result; result = goog.object.getValues(rTree.find([2, 3, 2, 3])); expect(result).to.contain(2); @@ -31,26 +105,6 @@ describe('ol.structs.RTree', function() { expect(goog.object.getCount(rTree.find([5, 6, 5, 6]))).to.be(0); }); - it('can store thousands of items and find fast', function() { - for (var i = 7; i <= 10000; ++i) { - rTree.put([ - Math.random() * -10, Math.random() * 10, - Math.random() * -10, Math.random() * 10 - ], i); - } - expect(goog.object.getCount(rTree.find([-10, 10, -10, 10]))).to.be(10000); - var result = rTree.find([0, 0, 0, 0]); - expect(goog.object.getCount(result)).to.be(9995); - var values = goog.object.getValues(result); - expect(values).to.contain(1); - expect(values).not.to.contain(2); - expect(values).not.to.contain(3); - expect(values).not.to.contain(4); - expect(values).not.to.contain(5); - expect(values).not.to.contain(6); - expect(values).to.contain(7); - }); - }); });