@thi.ng/distance
Version:
N-dimensional distance metrics & K-nearest neighborhoods for point queries
80 lines (79 loc) • 1.88 kB
JavaScript
import { clamp0 } from "@thi.ng/math/interval";
import { DIST_SQ, DIST_SQ1, DIST_SQ2, DIST_SQ3 } from "./squared.js";
class Radial {
constructor(dist, target, radius = Infinity) {
this.dist = dist;
this.target = target;
this.radius = radius;
this.setRadius(radius);
}
_r;
_items;
/**
* Clears current results.
*/
reset() {
this._items = [];
return this;
}
/**
* Resets search/reference position and clears current results.
*
* @param target
*/
setTarget(target) {
this.target = target;
this.reset();
}
/**
* Resets search/query radius and clears current results.
*
* @param r
*/
setRadius(r) {
this.radius = clamp0(r);
this._r = this.dist.to(this.radius);
this.reset();
}
/**
* Returns an array of current neighbor result tuples (each `[dist, val]`).
*
* @remarks
* Use {@link Radial.values} to obtain result values **without** their
* distance metrics.
*/
deref() {
return this._items;
}
/**
* Similar to {@link Radial.deref}, but returns array of result values **without**
* their distance metrics.
*/
values() {
return this._items.map((x) => x[1]);
}
includesDistance(d, eucledian = true) {
return (eucledian ? this.dist.to(d) : d) <= this._r;
}
includesPosition(pos) {
return this.dist.metric(this.target, pos) < this._r;
}
consider(pos, val) {
const d = this.dist.metric(this.target, pos);
if (d <= this._r) {
this._items.push([d, val]);
}
return d;
}
}
const radial = (p, r, dist = DIST_SQ) => new Radial(dist, p, r);
const radial2 = (p, r, dist = DIST_SQ2) => new Radial(dist, p, r);
const radial3 = (p, r, dist = DIST_SQ3) => new Radial(dist, p, r);
const radialN = (p, r, dist = DIST_SQ1) => new Radial(dist, p, r);
export {
Radial,
radial,
radial2,
radial3,
radialN
};