UNPKG

@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
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 };