-
-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(distance): add Radial neighborhood impls
- add radial/2/3/N() factories
- Loading branch information
1 parent
26a171d
commit 667fed9
Showing
4 changed files
with
144 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import type { IDeref } from "@thi.ng/api"; | ||
import { clamp0 } from "@thi.ng/math/interval"; | ||
import type { ReadonlyVec } from "@thi.ng/vectors"; | ||
import type { IDistance, INeighborhood, Neighbor } from "./api.js"; | ||
import { DIST_SQ, DIST_SQ1, DIST_SQ2, DIST_SQ3 } from "./squared.js"; | ||
|
||
/** | ||
* A {@link INeighborhood} implementation for radial neighbor queries around a | ||
* given target location, initial query radius and {@link IDistance} metric to | ||
* determine proximity. Unbounded and unsorted version of {@link KNearest}. | ||
* | ||
* @remarks | ||
* Qualifying neighbors will be accumulated in order of processing via an | ||
* internal array and can be obtained via {@link Radial.deref} or | ||
* {@link Radial.values}. | ||
* | ||
* @typeParam D - spatial position for distance metric | ||
* @typeParam T - indexed value | ||
*/ | ||
export class Radial<D, T> | ||
implements INeighborhood<D, T>, IDeref<Neighbor<T>[]> | ||
{ | ||
protected _r!: number; | ||
protected _items!: [number, T][]; | ||
|
||
constructor( | ||
public readonly dist: IDistance<D>, | ||
public target: D, | ||
public radius = Infinity | ||
) { | ||
this.setRadius(radius); | ||
} | ||
|
||
/** | ||
* Clears current results. | ||
*/ | ||
reset() { | ||
this._items = []; | ||
return this; | ||
} | ||
|
||
/** | ||
* Resets search/reference position and clears current results. | ||
* | ||
* @param target | ||
*/ | ||
setTarget(target: D) { | ||
this.target = target; | ||
this.reset(); | ||
} | ||
|
||
/** | ||
* Resets search/query radius and clears current results. | ||
* | ||
* @param r | ||
*/ | ||
setRadius(r: number) { | ||
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: number, eucledian = true) { | ||
return (eucledian ? this.dist.to(d) : d) <= this._r; | ||
} | ||
|
||
consider(pos: D, val: T) { | ||
const d = this.dist.metric(this.target, pos); | ||
if (d <= this._r) { | ||
this._items.push([d, val]); | ||
} | ||
return d; | ||
} | ||
} | ||
|
||
/** | ||
* Defines a {@link Radial} instance for arbitrary length vector positions | ||
* and, by default, using an infinite region radius and {@link DIST_SQ} distance | ||
* metric. | ||
* | ||
* @param p - | ||
* @param r - | ||
* @param dist - | ||
*/ | ||
export const radial = <T>(p: ReadonlyVec, r?: number, dist = DIST_SQ) => | ||
new Radial<ReadonlyVec, T>(dist, p, r); | ||
|
||
/** | ||
* Defines a {@link Radial} instance for 2D vector positions and, by default, | ||
* using an infinite region radius and {@link DIST_SQ2} distance metric. | ||
* | ||
* @param p - | ||
* @param r - | ||
* @param dist - | ||
*/ | ||
export const radial2 = <T>(p: ReadonlyVec, r?: number, dist = DIST_SQ2) => | ||
new Radial<ReadonlyVec, T>(dist, p, r); | ||
|
||
/** | ||
* Defines a {@link Radial} instance for 3D vector positions, by default, | ||
* using an infinite region radius and {@link DIST_SQ3} distance metric. | ||
* | ||
* @param p - | ||
* @param r - | ||
* @param dist - | ||
*/ | ||
export const radial3 = <T>(p: ReadonlyVec, r?: number, dist = DIST_SQ3) => | ||
new Radial<ReadonlyVec, T>(dist, p, r); | ||
|
||
/** | ||
* Defines a {@link Radial} instance for numeric positions and, by default, | ||
* using an infinite region radius and {@link DIST_SQ1} distance metric. | ||
* | ||
* @param p - | ||
* @param r - | ||
* @param dist - | ||
*/ | ||
export const radialN = <T>(p: number, r?: number, dist = DIST_SQ1) => | ||
new Radial<number, T>(dist, p, r); |