@thi.ng/geom-accel
Version:
n-D spatial indexing data structures with a shared ES6 Map/Set-like API
120 lines (119 loc) • 2.93 kB
JavaScript
import { EPS } from "@thi.ng/math/api";
import { map } from "@thi.ng/transducers/map";
import { div } from "@thi.ng/vectors/div";
import { equals } from "@thi.ng/vectors/equals";
import { floor } from "@thi.ng/vectors/floor";
import { subN } from "@thi.ng/vectors/subn";
import { __ensureRes, __into } from "./utils.js";
class ASpatialGrid {
constructor(_min, _size, _res) {
this._min = _min;
this._size = _size;
this._res = _res;
__ensureRes(_res);
floor(null, this._res);
this._res1 = subN([], this._res, 1);
this._invSize = div([], this._res, _size);
this._num = 0;
}
_cells;
_num;
_invSize;
_res1;
get size() {
return this._num;
}
*[Symbol.iterator]() {
const cells = this._cells;
for (let i = cells.length; i-- > 0; ) {
if (cells[i]) yield* cells[i];
}
}
keys() {
return map((p) => p[0], this);
}
values() {
return map((p) => p[1], this);
}
copy() {
const copy = this.empty();
copy._num = this._num;
const src = this._cells;
const dest = copy._cells;
for (let i = src.length; i-- > 0; ) {
dest[i] = src[i] ? src[i].slice() : null;
}
return copy;
}
clear() {
this._cells.fill(null);
this._num = 0;
}
has(k, eps = EPS) {
return !!this.find(k, eps);
}
get(k, eps = EPS) {
const pair = this.find(k, eps);
return pair ? pair[1] : void 0;
}
set(k, v, eps = EPS) {
if (eps >= 0 && this.query(k, eps, 1).length) return false;
const id = this.findIndex(k);
const cell = this._cells[id];
if (!cell) {
this._cells[id] = [[k, v]];
} else {
cell.push([k, v]);
}
this._num++;
return true;
}
into(pairs, eps = EPS) {
return __into(this, pairs, eps);
}
remove(k) {
const id = this.findIndex(k);
const cell = this._cells[id];
if (!cell) return false;
for (let i = cell.length; i-- > 0; ) {
if (equals(cell[i][0], k)) {
cell.splice(i, 1);
this._num--;
return true;
}
}
return false;
}
query(q, radius, limit, acc) {
return this.doQuery((p) => p, q, radius, limit, acc);
}
queryKeys(q, radius, limit, acc) {
return this.doQuery((p) => p[0], q, radius, limit, acc);
}
queryValues(q, radius, limit, acc) {
return this.doQuery((p) => p[1], q, radius, limit, acc);
}
queryCell(dist, heap, c, k, limit) {
for (let i = c.length; i-- > 0; ) {
const d = dist(c[i][0], k);
if (d <= heap.values[0][0]) {
heap.length >= limit ? heap.pushPop([d, c[i]]) : heap.push([d, c[i]]);
}
}
}
find(k, eps) {
if (eps > 0) {
const res = this.query(k, EPS, 1);
return res.length ? res[0] : void 0;
}
const cell = this._cells[this.findIndex(k)];
if (cell) {
for (let i = cell.length; i-- > 0; ) {
if (equals(cell[i][0], k)) return cell[i];
}
}
}
}
export {
ASpatialGrid
};