mirror of
https://github.com/mourner/flatbush.git
synced 2025-12-08 17:36:26 +00:00
first commit
This commit is contained in:
commit
fc8d6cfbbd
31
debug.js
Normal file
31
debug.js
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
var flatbush = require('./');
|
||||
|
||||
var N = 1000000;
|
||||
var hilbertOrder = 16;
|
||||
|
||||
console.time('gen data');
|
||||
var coords = [];
|
||||
var spaceSize = 100;
|
||||
var boxSize = 1;
|
||||
for (var i = 0; i < N; i++) {
|
||||
var x = Math.random() * (spaceSize - boxSize);
|
||||
var y = Math.random() * (spaceSize - boxSize);
|
||||
var x2 = x + Math.random() * boxSize;
|
||||
var y2 = y + Math.random() * boxSize;
|
||||
coords.push(x, y, x2, y2);
|
||||
}
|
||||
console.timeEnd('gen data');
|
||||
|
||||
console.time('flatbush');
|
||||
var index = flatbush(N);
|
||||
for (var i = 0; i < coords.length; i += 4) {
|
||||
index.add(
|
||||
coords[i],
|
||||
coords[i + 1],
|
||||
coords[i + 2],
|
||||
coords[i + 3]);
|
||||
}
|
||||
index.finish();
|
||||
// console.log(index.data);
|
||||
console.timeEnd('flatbush');
|
||||
175
index.js
Normal file
175
index.js
Normal file
@ -0,0 +1,175 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = flatbush;
|
||||
|
||||
function flatbush(numItems, nodeSize, hilbertOrder) {
|
||||
return new Flatbush(numItems, nodeSize, hilbertOrder);
|
||||
}
|
||||
|
||||
function Flatbush(numItems, nodeSize, hilbertOrder) {
|
||||
|
||||
this._numItems = numItems;
|
||||
this._nodeSize = nodeSize || 16;
|
||||
this._hilbertOrder = hilbertOrder || 16;
|
||||
|
||||
// calculate the total number of nodes in the R-tree to allocate space for
|
||||
var n = numItems;
|
||||
var numNodes = n;
|
||||
do {
|
||||
n = Math.ceil(n / this._nodeSize);
|
||||
numNodes += n;
|
||||
} while (n !== 1);
|
||||
|
||||
this.data = new Float64Array(numNodes * 5);
|
||||
this._hilbertValues = new Uint32Array(numItems);
|
||||
|
||||
this._numAdded = 0;
|
||||
this._pos = 0;
|
||||
|
||||
this._minX = Infinity;
|
||||
this._minY = Infinity;
|
||||
this._maxX = -Infinity;
|
||||
this._maxY = -Infinity;
|
||||
}
|
||||
|
||||
Flatbush.prototype = {
|
||||
add: function (minX, minY, maxX, maxY) {
|
||||
this.data[this._pos++] = this._numAdded++;
|
||||
this.data[this._pos++] = minX;
|
||||
this.data[this._pos++] = minY;
|
||||
this.data[this._pos++] = maxX;
|
||||
this.data[this._pos++] = maxY;
|
||||
|
||||
if (minX < this._minX) this._minX = minX;
|
||||
if (minY < this._minY) this._minY = minY;
|
||||
if (maxX > this._maxX) this._maxX = maxX;
|
||||
if (maxY > this._maxY) this._maxY = maxY;
|
||||
},
|
||||
|
||||
finish: function () {
|
||||
if (this._numAdded !== this._numItems) {
|
||||
throw new Error('The number of items added does not match the number in the constructor.')
|
||||
}
|
||||
|
||||
var width = this._maxX - this._minX;
|
||||
var height = this._maxY - this._minY;
|
||||
var hilbertMax = Math.pow(2, this._hilbertOrder) - 1;
|
||||
|
||||
for (var i = 0; i < this._numItems; i++) {
|
||||
var x = Math.floor(hilbertMax * this.data[5 * i + 1] / width);
|
||||
var y = Math.floor(hilbertMax * this.data[5 * i + 2] / height);
|
||||
this._hilbertValues[i] = hilbert(this._hilbertOrder, x, y);
|
||||
}
|
||||
|
||||
// sort boxes by hilbert value
|
||||
sort(this._hilbertValues, this.data, 0, this._numItems - 1);
|
||||
|
||||
// TODO generate remaining nodes
|
||||
}
|
||||
};
|
||||
|
||||
function sort(values, boxes, left, right) {
|
||||
if (left >= right) return;
|
||||
|
||||
var i = left + 1;
|
||||
var j = right;
|
||||
|
||||
swap(values, boxes, (left + right) >> 1, i);
|
||||
if (values[left] > values[right]) swap(values, boxes, left, right);
|
||||
if (values[i] > values[right]) swap(values, boxes, i, right);
|
||||
if (values[left] > values[i]) swap(values, boxes, left, i);
|
||||
|
||||
var temp = values[i];
|
||||
while (true) {
|
||||
do i++; while (values[i] < temp);
|
||||
do j--; while (values[j] > temp);
|
||||
if (j < i) break;
|
||||
swap(values, boxes, i, j);
|
||||
}
|
||||
values[left + 1] = values[j];
|
||||
values[j] = temp;
|
||||
|
||||
if (right - i + 1 >= j - left) {
|
||||
sort(values, boxes, i, right);
|
||||
sort(values, boxes, left, j - 1);
|
||||
} else {
|
||||
sort(values, boxes, left, j - 1);
|
||||
sort(values, boxes, i, right);
|
||||
}
|
||||
}
|
||||
|
||||
function swap(values, boxes, i, j) {
|
||||
var temp = values[i];
|
||||
values[i] = values[j];
|
||||
values[j] = temp;
|
||||
|
||||
var k = 5 * i;
|
||||
var m = 5 * j;
|
||||
|
||||
var a = boxes[k];
|
||||
var b = boxes[k + 1];
|
||||
var c = boxes[k + 2];
|
||||
var d = boxes[k + 3];
|
||||
var e = boxes[k + 4];
|
||||
boxes[k] = boxes[m];
|
||||
boxes[k + 1] = boxes[m + 1];
|
||||
boxes[k + 2] = boxes[m + 2];
|
||||
boxes[k + 3] = boxes[m + 3];
|
||||
boxes[k + 4] = boxes[m + 4];
|
||||
boxes[m] = a;
|
||||
boxes[m + 1] = b;
|
||||
boxes[m + 2] = c;
|
||||
boxes[m + 3] = d;
|
||||
boxes[m + 4] = e;
|
||||
}
|
||||
|
||||
// Fast Hilbert curve algorithm by http://threadlocalmutex.com/
|
||||
// Ported from C++ https://github.com/rawrunprotected/hilbert_curves (public domain)
|
||||
function hilbert(n, x, y) {
|
||||
x = x << (16 - n);
|
||||
y = y << (16 - n);
|
||||
|
||||
var a = x ^ y;
|
||||
var b = 0xFFFF ^ a;
|
||||
var c = 0xFFFF ^ (x | y);
|
||||
var d = x & (y ^ 0xFFFF);
|
||||
|
||||
var A = a | (b >> 1);
|
||||
var B = (a >> 1) ^ a;
|
||||
var C = ((c >> 1) ^ (b & (d >> 1))) ^ c;
|
||||
var D = ((a & (c >> 1)) ^ (d >> 1)) ^ d;
|
||||
|
||||
a = A; b = B; c = C; d = D;
|
||||
A = ((a & (a >> 2)) ^ (b & (b >> 2)));
|
||||
B = ((a & (b >> 2)) ^ (b & ((a ^ b) >> 2)));
|
||||
C ^= ((a & (c >> 2)) ^ (b & (d >> 2)));
|
||||
D ^= ((b & (c >> 2)) ^ ((a ^ b) & (d >> 2)));
|
||||
|
||||
a = A; b = B; c = C; d = D;
|
||||
A = ((a & (a >> 4)) ^ (b & (b >> 4)));
|
||||
B = ((a & (b >> 4)) ^ (b & ((a ^ b) >> 4)));
|
||||
C ^= ((a & (c >> 4)) ^ (b & (d >> 4)));
|
||||
D ^= ((b & (c >> 4)) ^ ((a ^ b) & (d >> 4)));
|
||||
|
||||
a = A; b = B; c = C; d = D;
|
||||
C ^= ((a & (c >> 8)) ^ (b & (d >> 8)));
|
||||
D ^= ((b & (c >> 8)) ^ ((a ^ b) & (d >> 8)));
|
||||
|
||||
a = C ^ (C >> 1);
|
||||
b = D ^ (D >> 1);
|
||||
|
||||
var i0 = x ^ y;
|
||||
var i1 = b | (0xFFFF ^ (i0 | a));
|
||||
|
||||
i0 = (i0 | (i0 << 8)) & 0x00FF00FF;
|
||||
i0 = (i0 | (i0 << 4)) & 0x0F0F0F0F;
|
||||
i0 = (i0 | (i0 << 2)) & 0x33333333;
|
||||
i0 = (i0 | (i0 << 1)) & 0x55555555;
|
||||
|
||||
i1 = (i1 | (i1 << 8)) & 0x00FF00FF;
|
||||
i1 = (i1 | (i1 << 4)) & 0x0F0F0F0F;
|
||||
i1 = (i1 | (i1 << 2)) & 0x33333333;
|
||||
i1 = (i1 | (i1 << 1)) & 0x55555555;
|
||||
|
||||
return (((i1 << 1) | i0) >> (32 - 2 * n)) >>> 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user