Skip to content

Commit

Permalink
much simpler API for customizing data format
Browse files Browse the repository at this point in the history
  • Loading branch information
mourner committed Jul 8, 2013
1 parent 14314c2 commit 81c6f28
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 22 deletions.
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,10 @@ Returns an array of data items (points or rectangles) that the given bounding bo

#### Data Format

By default, rbush assumes the format of data points as `[minX, minY, maxX, maxY]`. However you can customize this by redefining `sortX`, `sortY` and `toBBox` methods like this:
By default, rbush assumes the format of data points as `[minX, minY, maxX, maxY]`. However you can customize by providing a `format` argument (an array with `minX`, `minY`, `maxX`, `maxY` accessors as strings) to `rbush` like this:

```js
var tree = rbush();

tree.sortX = function (a, b) { return a.minLng > b.minLng ? 1 : -1; };
tree.sortY = function (a, b) { return a.minLat > b.minLat ? 1 : -1; };
tree.toBBox = function (a) { return [a.minLng, a.minLat, a.maxLng, a.maxLat]; };
var tree = rbush(4, ['.minLng', '.minLat', '.maxLng', '.maxLat']);

tree.load([{id: 'foo', minLng: 30, minLat: 50, maxLng: 40, maxLat: 60}, ...]);
```
Expand Down
33 changes: 17 additions & 16 deletions rbush.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,30 @@

(function () { 'use strict';

function rbush(maxEntries) {
function rbush(maxEntries, format) {
// jshint newcap: false, validthis: true, evil: true

if (!(this instanceof rbush)) {
// jshint newcap: false
return new rbush(maxEntries);
return new rbush(maxEntries, format);
}

if (!maxEntries) {
throw new Error("Provide a maxEntries argument to rbush constructor");
}
this._maxEntries = Math.max(4, maxEntries);
this._minFill = Math.max(2, Math.floor(this._maxEntries * 0.4));
};

rbush.prototype = {

// redefine the next 3 methods to suit your data format
// customizes data format (minX, minY, maxX, maxY accessors)

// compare functions for sorting by x and y coordinate
sortX: function (a, b) { return a[0] > b[0] ? 1 : -1; },
sortY: function (a, b) { return a[1] > b[1] ? 1 : -1; },
format = format || ['[0]', '[1]', '[2]', '[3]'];

// get bounding box in the form of [minX, minY, maxX, maxY] given a data item
toBBox: function (a) { return a; },
this._sortMinX = new Function('a', 'b', 'return a' + format[0] + ' > b' + format[0] + ' ? 1 : -1;');
this._sortMinY = new Function('a', 'b', 'return a' + format[1] + ' > b' + format[1] + ' ? 1 : -1;');
this._toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
}

rbush.prototype = {

// recursively search for objects in a given bbox
search: function (bbox) {
Expand All @@ -46,7 +47,7 @@ rbush.prototype = {
},

addOne: function (item) {
var node = this._chooseSubtree(this.toBBox(item), this.data);
var node = this._chooseSubtree(this._toBBox(item), this.data);
// TODO reinsert, split (choose split axis, choose split index), insert
},

Expand All @@ -71,7 +72,7 @@ rbush.prototype = {

if (!node.leaf) {
this._search(bbox, child, result);
} else if (this._intersects(bbox, this.toBBox(child))) {
} else if (this._intersects(bbox, this._toBBox(child))) {
result.push(child);
}
}
Expand All @@ -96,12 +97,12 @@ rbush.prototype = {
// target number of root entries
M = Math.ceil(N / Math.pow(M, Math.ceil(Math.log(N) / Math.log(M)) - 1));

items.sort(this.sortX);
items.sort(this._sortMinX);
}

var N1 = Math.ceil(N / M) * Math.ceil(Math.sqrt(M)),
N2 = Math.ceil(N / M),
sortFn = level % 2 === 1 ? this.sortX : this.sortY,
sortFn = level % 2 === 1 ? this._sortMinX : this._sortMinY,
i, j, slice, sliceLen, childNode;

// create S x S entries for the node and build from there recursively
Expand All @@ -126,7 +127,7 @@ rbush.prototype = {
child = node.children[i];

if (node.leaf) {
this._extend(node.bbox, this.toBBox(child));
this._extend(node.bbox, this._toBBox(child));
} else {
this._calcBBoxes(child);
this._extend(node.bbox, child.bbox);
Expand Down
8 changes: 8 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ describe('rbush', function () {
], "bbox":[70,0,95,95]
}], "bbox":[0,0,95,95]};

describe('constructor', function () {
it('accepts a format argument to customize the data format', function () {

var tree = rbush(4, ['.minLng', '.minLat', '.maxLng', '.maxLat']);
assert.deepEqual(tree._toBBox({minLng: 1, minLat: 2, maxLng: 3, maxLat: 4}), [1, 2, 3, 4]);
});
});

describe('load', function () {
it('bulk-loads the given data given max node entries and forms a proper search tree', function () {

Expand Down

0 comments on commit 81c6f28

Please sign in to comment.