@thi.ng/distance 2.4.32 → 2.4.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/api.js +0 -1
- package/argmin.js +37 -74
- package/eucledian.js +21 -27
- package/haversine.js +10 -9
- package/knearest.js +94 -150
- package/manhattan.js +27 -70
- package/nearest.js +46 -84
- package/package.json +12 -10
- package/radial.js +75 -117
- package/squared.js +21 -15
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
package/api.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/argmin.js
CHANGED
|
@@ -1,82 +1,45 @@
|
|
|
1
1
|
import { isFunction } from "@thi.ng/checks/is-function";
|
|
2
2
|
import { knearest } from "./knearest.js";
|
|
3
3
|
import { DIST_SQ, DIST_SQ1 } from "./squared.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
* @param p -
|
|
15
|
-
* @param samples -
|
|
16
|
-
* @param dist -
|
|
17
|
-
*/
|
|
18
|
-
export const argmin = (p, samples, dist = DIST_SQ) => {
|
|
19
|
-
const distFn = isFunction(dist) ? dist : dist.metric;
|
|
20
|
-
let minD = Infinity;
|
|
21
|
-
let minArg = -1;
|
|
22
|
-
for (let i = 0, n = samples.length; i < n; i++) {
|
|
23
|
-
const d = distFn(p, samples[i]);
|
|
24
|
-
if (d < minD) {
|
|
25
|
-
minD = d;
|
|
26
|
-
minArg = i;
|
|
27
|
-
}
|
|
4
|
+
const argmin = (p, samples, dist = DIST_SQ) => {
|
|
5
|
+
const distFn = isFunction(dist) ? dist : dist.metric;
|
|
6
|
+
let minD = Infinity;
|
|
7
|
+
let minArg = -1;
|
|
8
|
+
for (let i = 0, n = samples.length; i < n; i++) {
|
|
9
|
+
const d = distFn(p, samples[i]);
|
|
10
|
+
if (d < minD) {
|
|
11
|
+
minD = d;
|
|
12
|
+
minArg = i;
|
|
28
13
|
}
|
|
29
|
-
|
|
14
|
+
}
|
|
15
|
+
return minArg;
|
|
30
16
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
17
|
+
const argminN = (p, samples, dist = DIST_SQ1) => {
|
|
18
|
+
const distFn = isFunction(dist) ? dist : dist.metric;
|
|
19
|
+
let minD = Infinity;
|
|
20
|
+
let minArg = -1;
|
|
21
|
+
for (let i = 0, n = samples.length; i < n; i++) {
|
|
22
|
+
const d = distFn(p, samples[i]);
|
|
23
|
+
if (d < minD) {
|
|
24
|
+
minD = d;
|
|
25
|
+
minArg = i;
|
|
41
26
|
}
|
|
42
|
-
|
|
27
|
+
}
|
|
28
|
+
return minArg;
|
|
43
29
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Similar to {@link argmin}, but for k-nearest queries.
|
|
61
|
-
*
|
|
62
|
-
* @param k -
|
|
63
|
-
* @param p -
|
|
64
|
-
* @param samples -
|
|
65
|
-
* @param dist -
|
|
66
|
-
*/
|
|
67
|
-
export const argminK = (k, p, samples, dist = DIST_SQ) => {
|
|
68
|
-
const neighborhood = knearest(p, k, Infinity, dist);
|
|
69
|
-
for (let i = 0, n = samples.length; i < n; i++) {
|
|
70
|
-
neighborhood.consider(samples[i], i);
|
|
71
|
-
}
|
|
72
|
-
return neighborhood.values();
|
|
30
|
+
const argminT = (p, samples, key, dist) => argmin(key(p), samples.map(key), dist);
|
|
31
|
+
const argminK = (k, p, samples, dist = DIST_SQ) => {
|
|
32
|
+
const neighborhood = knearest(p, k, Infinity, dist);
|
|
33
|
+
for (let i = 0, n = samples.length; i < n; i++) {
|
|
34
|
+
neighborhood.consider(samples[i], i);
|
|
35
|
+
}
|
|
36
|
+
return neighborhood.values();
|
|
37
|
+
};
|
|
38
|
+
const argminKT = (k, p, samples, key, dist) => argminK(k, key(p), samples.map(key), dist);
|
|
39
|
+
export {
|
|
40
|
+
argmin,
|
|
41
|
+
argminK,
|
|
42
|
+
argminKT,
|
|
43
|
+
argminN,
|
|
44
|
+
argminT
|
|
73
45
|
};
|
|
74
|
-
/**
|
|
75
|
-
* Similar to {@link argminT}, but for k-nearest queries.
|
|
76
|
-
*
|
|
77
|
-
* @param k -
|
|
78
|
-
* @param p -
|
|
79
|
-
* @param samples -
|
|
80
|
-
* @param dist -
|
|
81
|
-
*/
|
|
82
|
-
export const argminKT = (k, p, samples, key, dist) => argminK(k, key(p), samples.map(key), dist);
|
package/eucledian.js
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
import { dist, dist2, dist3 } from "@thi.ng/vectors/dist";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
2
|
+
class Eucledian {
|
|
3
|
+
constructor(metric) {
|
|
4
|
+
this.metric = metric;
|
|
5
|
+
}
|
|
6
|
+
to(x) {
|
|
7
|
+
return x;
|
|
8
|
+
}
|
|
9
|
+
from(x) {
|
|
10
|
+
return x;
|
|
11
|
+
}
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export const EUCLEDIAN2 = new Eucledian(dist2);
|
|
26
|
-
/**
|
|
27
|
-
* Eucledian distance metric for 3d vectors.
|
|
28
|
-
*/
|
|
29
|
-
export const EUCLEDIAN3 = new Eucledian(dist3);
|
|
13
|
+
const EUCLEDIAN = new Eucledian(dist);
|
|
14
|
+
const EUCLEDIAN1 = new Eucledian((a, b) => Math.abs(a - b));
|
|
15
|
+
const EUCLEDIAN2 = new Eucledian(dist2);
|
|
16
|
+
const EUCLEDIAN3 = new Eucledian(dist3);
|
|
17
|
+
export {
|
|
18
|
+
EUCLEDIAN,
|
|
19
|
+
EUCLEDIAN1,
|
|
20
|
+
EUCLEDIAN2,
|
|
21
|
+
EUCLEDIAN3,
|
|
22
|
+
Eucledian
|
|
23
|
+
};
|
package/haversine.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
distHaversineLatLon,
|
|
3
|
+
distHaversineLonLat
|
|
4
|
+
} from "@thi.ng/vectors/dist-haversine";
|
|
2
5
|
import { Eucledian } from "./eucledian.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export const HAVERSINE_LONLAT = new Eucledian(distHaversineLonLat);
|
|
6
|
+
const HAVERSINE_LATLON = new Eucledian(distHaversineLatLon);
|
|
7
|
+
const HAVERSINE_LONLAT = new Eucledian(distHaversineLonLat);
|
|
8
|
+
export {
|
|
9
|
+
HAVERSINE_LATLON,
|
|
10
|
+
HAVERSINE_LONLAT
|
|
11
|
+
};
|
package/knearest.js
CHANGED
|
@@ -2,155 +2,99 @@ import { assert } from "@thi.ng/errors/assert";
|
|
|
2
2
|
import { Heap } from "@thi.ng/heaps/heap";
|
|
3
3
|
import { clamp0 } from "@thi.ng/math/interval";
|
|
4
4
|
import { DIST_SQ, DIST_SQ1, DIST_SQ2, DIST_SQ3 } from "./squared.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
* their distance metrics.
|
|
87
|
-
*/
|
|
88
|
-
values() {
|
|
89
|
-
return this.deref().map((x) => x[1]);
|
|
90
|
-
}
|
|
91
|
-
includesDistance(d, eucledian = true) {
|
|
92
|
-
return (eucledian ? this.dist.to(d) : d) <= this._currR;
|
|
93
|
-
}
|
|
94
|
-
includesPosition(pos) {
|
|
95
|
-
return this.dist.metric(this.target, pos) < this._currR;
|
|
96
|
-
}
|
|
97
|
-
consider(pos, val) {
|
|
98
|
-
const d = this.dist.metric(this.target, pos);
|
|
99
|
-
if (d <= this._currR) {
|
|
100
|
-
const heap = this._heap;
|
|
101
|
-
if (heap.length === this.k) {
|
|
102
|
-
heap.pushPop([d, val]);
|
|
103
|
-
this._currR = heap.peek()[0];
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
heap.push([d, val]);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return d;
|
|
5
|
+
class KNearest {
|
|
6
|
+
constructor(dist, target, k, radius = Infinity, sorted = false) {
|
|
7
|
+
this.dist = dist;
|
|
8
|
+
this.target = target;
|
|
9
|
+
this.k = k;
|
|
10
|
+
this.radius = radius;
|
|
11
|
+
this.sorted = sorted;
|
|
12
|
+
this.radius = clamp0(radius);
|
|
13
|
+
this.setK(k);
|
|
14
|
+
}
|
|
15
|
+
_currR;
|
|
16
|
+
_heap = new Heap(null, {
|
|
17
|
+
compare: (a, b) => b[0] - a[0]
|
|
18
|
+
});
|
|
19
|
+
reset() {
|
|
20
|
+
this._currR = this.dist.to(this.radius);
|
|
21
|
+
this._heap.clear();
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resets search/reference position.
|
|
26
|
+
*
|
|
27
|
+
* @param target
|
|
28
|
+
*/
|
|
29
|
+
setTarget(target) {
|
|
30
|
+
this.target = target;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resets max. search/query radius and clears current results.
|
|
34
|
+
*
|
|
35
|
+
* @param r
|
|
36
|
+
*/
|
|
37
|
+
setRadius(r) {
|
|
38
|
+
this.radius = clamp0(r);
|
|
39
|
+
this.reset();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resets `k-nearest` limit and clears current results.
|
|
43
|
+
*
|
|
44
|
+
* @param r
|
|
45
|
+
*/
|
|
46
|
+
setK(k) {
|
|
47
|
+
assert(k > 0, `invalid k (must be > 0)`);
|
|
48
|
+
this.k = k;
|
|
49
|
+
this.reset();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Returns an array of current nearest neighbor result tuples (each `[dist,
|
|
53
|
+
* val]`). The array will contain at most `k` items and if the `sorted` ctor
|
|
54
|
+
* arg was true, will be sorted by distance.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* Use {@link KNearest.values} to obtain result values **without** their distance
|
|
58
|
+
* metrics.
|
|
59
|
+
*/
|
|
60
|
+
deref() {
|
|
61
|
+
return this.sorted ? this._heap.max() : this._heap.values;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Similar to {@link KNearest.deref}, but returns array of result values **without**
|
|
65
|
+
* their distance metrics.
|
|
66
|
+
*/
|
|
67
|
+
values() {
|
|
68
|
+
return this.deref().map((x) => x[1]);
|
|
69
|
+
}
|
|
70
|
+
includesDistance(d, eucledian = true) {
|
|
71
|
+
return (eucledian ? this.dist.to(d) : d) <= this._currR;
|
|
72
|
+
}
|
|
73
|
+
includesPosition(pos) {
|
|
74
|
+
return this.dist.metric(this.target, pos) < this._currR;
|
|
75
|
+
}
|
|
76
|
+
consider(pos, val) {
|
|
77
|
+
const d = this.dist.metric(this.target, pos);
|
|
78
|
+
if (d <= this._currR) {
|
|
79
|
+
const heap = this._heap;
|
|
80
|
+
if (heap.length === this.k) {
|
|
81
|
+
heap.pushPop([d, val]);
|
|
82
|
+
this._currR = heap.peek()[0];
|
|
83
|
+
} else {
|
|
84
|
+
heap.push([d, val]);
|
|
85
|
+
}
|
|
110
86
|
}
|
|
87
|
+
return d;
|
|
88
|
+
}
|
|
111
89
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
export const knearest = (p, k, r, dist = DIST_SQ, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
124
|
-
/**
|
|
125
|
-
* Defines a {@link KNearest} instance for 2D vector positions and, by default,
|
|
126
|
-
* using an infinite region radius and {@link DIST_SQ2} distance metric.
|
|
127
|
-
*
|
|
128
|
-
* @param p -
|
|
129
|
-
* @param k -
|
|
130
|
-
* @param r -
|
|
131
|
-
* @param dist -
|
|
132
|
-
* @param sorted -
|
|
133
|
-
*/
|
|
134
|
-
export const knearest2 = (p, k, r, dist = DIST_SQ2, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
135
|
-
/**
|
|
136
|
-
* Defines a {@link KNearest} instance for 3D vector positions, by default,
|
|
137
|
-
* using an infinite region radius and {@link DIST_SQ3} distance metric.
|
|
138
|
-
*
|
|
139
|
-
* @param p -
|
|
140
|
-
* @param k -
|
|
141
|
-
* @param r -
|
|
142
|
-
* @param dist -
|
|
143
|
-
* @param sorted -
|
|
144
|
-
*/
|
|
145
|
-
export const knearest3 = (p, k, r, dist = DIST_SQ3, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
146
|
-
/**
|
|
147
|
-
* Defines a {@link KNearest} instance for numeric positions and, by default,
|
|
148
|
-
* using an infinite region radius and {@link DIST_SQ1} distance metric.
|
|
149
|
-
*
|
|
150
|
-
* @param p -
|
|
151
|
-
* @param k -
|
|
152
|
-
* @param r -
|
|
153
|
-
* @param dist -
|
|
154
|
-
* @param sorted -
|
|
155
|
-
*/
|
|
156
|
-
export const knearestN = (p, k, r, dist = DIST_SQ1, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
90
|
+
const knearest = (p, k, r, dist = DIST_SQ, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
91
|
+
const knearest2 = (p, k, r, dist = DIST_SQ2, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
92
|
+
const knearest3 = (p, k, r, dist = DIST_SQ3, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
93
|
+
const knearestN = (p, k, r, dist = DIST_SQ1, sorted) => new KNearest(dist, p, k, r, sorted);
|
|
94
|
+
export {
|
|
95
|
+
KNearest,
|
|
96
|
+
knearest,
|
|
97
|
+
knearest2,
|
|
98
|
+
knearest3,
|
|
99
|
+
knearestN
|
|
100
|
+
};
|
package/manhattan.js
CHANGED
|
@@ -1,71 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
* // 30
|
|
20
|
-
*
|
|
21
|
-
* MANHATTAN2.from(30);
|
|
22
|
-
* // 21.213203435596427
|
|
23
|
-
*
|
|
24
|
-
* Math.hypot(15, 15) // <-- diagonal of manhattan square
|
|
25
|
-
* // 21.213203435596427
|
|
26
|
-
*
|
|
27
|
-
* Math.hypot(10, 20) // <-- actual eucledian dist
|
|
28
|
-
* // 22.360679774997898
|
|
29
|
-
*
|
|
30
|
-
* MANHATTAN2.to(21.213203435596427)
|
|
31
|
-
* // 30
|
|
32
|
-
*
|
|
33
|
-
* // however, starting w/ eucledian dist first
|
|
34
|
-
* e = mag([10, 20])
|
|
35
|
-
* // 22.360679774997898
|
|
36
|
-
*
|
|
37
|
-
* m = MANHATTAN2.to(e)
|
|
38
|
-
* // 31.622776601683793
|
|
39
|
-
*
|
|
40
|
-
* MANHATTAN2.from(m) === e
|
|
41
|
-
* // true
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export class Manhattan {
|
|
45
|
-
dim;
|
|
46
|
-
metric;
|
|
47
|
-
_invD;
|
|
48
|
-
constructor(dim, metric) {
|
|
49
|
-
this.dim = dim;
|
|
50
|
-
this.metric = metric;
|
|
51
|
-
this._invD = this.dim / Math.sqrt(dim);
|
|
52
|
-
}
|
|
53
|
-
to(x) {
|
|
54
|
-
return x * this._invD;
|
|
55
|
-
}
|
|
56
|
-
from(x) {
|
|
57
|
-
return Math.sqrt((x / this.dim) ** 2 * this.dim);
|
|
58
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
distManhattan,
|
|
3
|
+
distManhattan2,
|
|
4
|
+
distManhattan3
|
|
5
|
+
} from "@thi.ng/vectors/dist-manhattan";
|
|
6
|
+
class Manhattan {
|
|
7
|
+
constructor(dim, metric) {
|
|
8
|
+
this.dim = dim;
|
|
9
|
+
this.metric = metric;
|
|
10
|
+
this._invD = this.dim / Math.sqrt(dim);
|
|
11
|
+
}
|
|
12
|
+
_invD;
|
|
13
|
+
to(x) {
|
|
14
|
+
return x * this._invD;
|
|
15
|
+
}
|
|
16
|
+
from(x) {
|
|
17
|
+
return Math.sqrt((x / this.dim) ** 2 * this.dim);
|
|
18
|
+
}
|
|
59
19
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
export
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* Manhattan distance metric for 3d vectors.
|
|
70
|
-
*/
|
|
71
|
-
export const MANHATTAN3 = new Manhattan(3, distManhattan3);
|
|
20
|
+
const defManhattan = (dim) => new Manhattan(dim, distManhattan);
|
|
21
|
+
const MANHATTAN2 = new Manhattan(2, distManhattan2);
|
|
22
|
+
const MANHATTAN3 = new Manhattan(3, distManhattan3);
|
|
23
|
+
export {
|
|
24
|
+
MANHATTAN2,
|
|
25
|
+
MANHATTAN3,
|
|
26
|
+
Manhattan,
|
|
27
|
+
defManhattan
|
|
28
|
+
};
|
package/nearest.js
CHANGED
|
@@ -1,88 +1,50 @@
|
|
|
1
1
|
import { clamp0 } from "@thi.ng/math/interval";
|
|
2
2
|
import { DIST_SQ, DIST_SQ1, DIST_SQ2, DIST_SQ3 } from "./squared.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
radius;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
includesDistance(d, eucledian = true) {
|
|
38
|
-
return (eucledian ? this.dist.to(d) : d) <= this._currR;
|
|
39
|
-
}
|
|
40
|
-
includesPosition(pos) {
|
|
41
|
-
return this.dist.metric(this.target, pos) < this._currR;
|
|
42
|
-
}
|
|
43
|
-
consider(pos, val) {
|
|
44
|
-
const d = this.dist.metric(this.target, pos);
|
|
45
|
-
if (d <= this._currR) {
|
|
46
|
-
this._currR = d;
|
|
47
|
-
this.value = val;
|
|
48
|
-
}
|
|
49
|
-
return d;
|
|
3
|
+
class Nearest {
|
|
4
|
+
constructor(dist, target, radius = Infinity) {
|
|
5
|
+
this.dist = dist;
|
|
6
|
+
this.target = target;
|
|
7
|
+
this.radius = clamp0(radius);
|
|
8
|
+
this.reset();
|
|
9
|
+
}
|
|
10
|
+
radius;
|
|
11
|
+
_currR;
|
|
12
|
+
value;
|
|
13
|
+
reset() {
|
|
14
|
+
this._currR = this.dist.to(this.radius);
|
|
15
|
+
this.value = void 0;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns current nearest neighbor result tuple (`[dist, val]`) or
|
|
20
|
+
* undefined, if no such result exists (yet).
|
|
21
|
+
*/
|
|
22
|
+
deref() {
|
|
23
|
+
return this.value != void 0 ? [this._currR, this.value] : void 0;
|
|
24
|
+
}
|
|
25
|
+
includesDistance(d, eucledian = true) {
|
|
26
|
+
return (eucledian ? this.dist.to(d) : d) <= this._currR;
|
|
27
|
+
}
|
|
28
|
+
includesPosition(pos) {
|
|
29
|
+
return this.dist.metric(this.target, pos) < this._currR;
|
|
30
|
+
}
|
|
31
|
+
consider(pos, val) {
|
|
32
|
+
const d = this.dist.metric(this.target, pos);
|
|
33
|
+
if (d <= this._currR) {
|
|
34
|
+
this._currR = d;
|
|
35
|
+
this.value = val;
|
|
50
36
|
}
|
|
37
|
+
return d;
|
|
38
|
+
}
|
|
51
39
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* Defines a {@link Nearest} instance for 2D vector positions, by default,
|
|
64
|
-
* using an infinite region radius and {@link DIST_SQ2} distance metric.
|
|
65
|
-
*
|
|
66
|
-
* @param p -
|
|
67
|
-
* @param r -
|
|
68
|
-
* @param dist -
|
|
69
|
-
*/
|
|
70
|
-
export const nearest2 = (p, r, dist = DIST_SQ2) => new Nearest(dist, p, r);
|
|
71
|
-
/**
|
|
72
|
-
* Defines a {@link Nearest} instance for 3D vector positions, by default,
|
|
73
|
-
* using an infinite region radius and {@link DIST_SQ3} distance metric.
|
|
74
|
-
*
|
|
75
|
-
* @param p -
|
|
76
|
-
* @param r -
|
|
77
|
-
* @param dist -
|
|
78
|
-
*/
|
|
79
|
-
export const nearest3 = (p, r, dist = DIST_SQ3) => new Nearest(dist, p, r);
|
|
80
|
-
/**
|
|
81
|
-
* Defines a {@link Nearest} instance for numeric positions and, by default,
|
|
82
|
-
* using an infinite region radius and {@link DIST_SQ1} distance metric.
|
|
83
|
-
*
|
|
84
|
-
* @param p -
|
|
85
|
-
* @param r -
|
|
86
|
-
* @param dist -
|
|
87
|
-
*/
|
|
88
|
-
export const nearestN = (p, r, dist = DIST_SQ1) => new Nearest(dist, p, r);
|
|
40
|
+
const nearest = (p, r, dist = DIST_SQ) => new Nearest(dist, p, r);
|
|
41
|
+
const nearest2 = (p, r, dist = DIST_SQ2) => new Nearest(dist, p, r);
|
|
42
|
+
const nearest3 = (p, r, dist = DIST_SQ3) => new Nearest(dist, p, r);
|
|
43
|
+
const nearestN = (p, r, dist = DIST_SQ1) => new Nearest(dist, p, r);
|
|
44
|
+
export {
|
|
45
|
+
Nearest,
|
|
46
|
+
nearest,
|
|
47
|
+
nearest2,
|
|
48
|
+
nearest3,
|
|
49
|
+
nearestN
|
|
50
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/distance",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.34",
|
|
4
4
|
"description": "N-dimensional distance metrics & K-nearest neighborhoods for point queries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"author": "Karsten Schmidt (https://thi.ng)",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "yarn
|
|
27
|
+
"build": "yarn build:esbuild && yarn build:decl",
|
|
28
|
+
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
29
|
+
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
28
30
|
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
|
|
29
31
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
30
32
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
@@ -33,16 +35,16 @@
|
|
|
33
35
|
"test": "bun test"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@thi.ng/api": "^8.9.
|
|
37
|
-
"@thi.ng/checks": "^3.4.
|
|
38
|
-
"@thi.ng/errors": "^2.4.
|
|
39
|
-
"@thi.ng/heaps": "^2.1.
|
|
40
|
-
"@thi.ng/math": "^5.7.
|
|
41
|
-
"@thi.ng/vectors": "^7.8.
|
|
38
|
+
"@thi.ng/api": "^8.9.12",
|
|
39
|
+
"@thi.ng/checks": "^3.4.12",
|
|
40
|
+
"@thi.ng/errors": "^2.4.6",
|
|
41
|
+
"@thi.ng/heaps": "^2.1.48",
|
|
42
|
+
"@thi.ng/math": "^5.7.7",
|
|
43
|
+
"@thi.ng/vectors": "^7.8.9"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@microsoft/api-extractor": "^7.38.3",
|
|
45
|
-
"
|
|
47
|
+
"esbuild": "^0.19.8",
|
|
46
48
|
"rimraf": "^5.0.5",
|
|
47
49
|
"tools": "^0.0.1",
|
|
48
50
|
"typedoc": "^0.25.4",
|
|
@@ -111,5 +113,5 @@
|
|
|
111
113
|
],
|
|
112
114
|
"year": 2021
|
|
113
115
|
},
|
|
114
|
-
"gitHead": "
|
|
116
|
+
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
|
|
115
117
|
}
|
package/radial.js
CHANGED
|
@@ -1,121 +1,79 @@
|
|
|
1
1
|
import { clamp0 } from "@thi.ng/math/interval";
|
|
2
2
|
import { DIST_SQ, DIST_SQ1, DIST_SQ2, DIST_SQ3 } from "./squared.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* Similar to {@link Radial.deref}, but returns array of result values **without**
|
|
66
|
-
* their distance metrics.
|
|
67
|
-
*/
|
|
68
|
-
values() {
|
|
69
|
-
return this._items.map((x) => x[1]);
|
|
70
|
-
}
|
|
71
|
-
includesDistance(d, eucledian = true) {
|
|
72
|
-
return (eucledian ? this.dist.to(d) : d) <= this._r;
|
|
73
|
-
}
|
|
74
|
-
includesPosition(pos) {
|
|
75
|
-
return this.dist.metric(this.target, pos) < this._r;
|
|
76
|
-
}
|
|
77
|
-
consider(pos, val) {
|
|
78
|
-
const d = this.dist.metric(this.target, pos);
|
|
79
|
-
if (d <= this._r) {
|
|
80
|
-
this._items.push([d, val]);
|
|
81
|
-
}
|
|
82
|
-
return d;
|
|
3
|
+
class Radial {
|
|
4
|
+
constructor(dist, target, radius = Infinity) {
|
|
5
|
+
this.dist = dist;
|
|
6
|
+
this.target = target;
|
|
7
|
+
this.radius = radius;
|
|
8
|
+
this.setRadius(radius);
|
|
9
|
+
}
|
|
10
|
+
_r;
|
|
11
|
+
_items;
|
|
12
|
+
/**
|
|
13
|
+
* Clears current results.
|
|
14
|
+
*/
|
|
15
|
+
reset() {
|
|
16
|
+
this._items = [];
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resets search/reference position and clears current results.
|
|
21
|
+
*
|
|
22
|
+
* @param target
|
|
23
|
+
*/
|
|
24
|
+
setTarget(target) {
|
|
25
|
+
this.target = target;
|
|
26
|
+
this.reset();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resets search/query radius and clears current results.
|
|
30
|
+
*
|
|
31
|
+
* @param r
|
|
32
|
+
*/
|
|
33
|
+
setRadius(r) {
|
|
34
|
+
this.radius = clamp0(r);
|
|
35
|
+
this._r = this.dist.to(this.radius);
|
|
36
|
+
this.reset();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns an array of current neighbor result tuples (each `[dist, val]`).
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Use {@link Radial.values} to obtain result values **without** their
|
|
43
|
+
* distance metrics.
|
|
44
|
+
*/
|
|
45
|
+
deref() {
|
|
46
|
+
return this._items;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Similar to {@link Radial.deref}, but returns array of result values **without**
|
|
50
|
+
* their distance metrics.
|
|
51
|
+
*/
|
|
52
|
+
values() {
|
|
53
|
+
return this._items.map((x) => x[1]);
|
|
54
|
+
}
|
|
55
|
+
includesDistance(d, eucledian = true) {
|
|
56
|
+
return (eucledian ? this.dist.to(d) : d) <= this._r;
|
|
57
|
+
}
|
|
58
|
+
includesPosition(pos) {
|
|
59
|
+
return this.dist.metric(this.target, pos) < this._r;
|
|
60
|
+
}
|
|
61
|
+
consider(pos, val) {
|
|
62
|
+
const d = this.dist.metric(this.target, pos);
|
|
63
|
+
if (d <= this._r) {
|
|
64
|
+
this._items.push([d, val]);
|
|
83
65
|
}
|
|
66
|
+
return d;
|
|
67
|
+
}
|
|
84
68
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* Defines a {@link Radial} instance for 2D vector positions and, by default,
|
|
97
|
-
* using an infinite region radius and {@link DIST_SQ2} distance metric.
|
|
98
|
-
*
|
|
99
|
-
* @param p -
|
|
100
|
-
* @param r -
|
|
101
|
-
* @param dist -
|
|
102
|
-
*/
|
|
103
|
-
export const radial2 = (p, r, dist = DIST_SQ2) => new Radial(dist, p, r);
|
|
104
|
-
/**
|
|
105
|
-
* Defines a {@link Radial} instance for 3D vector positions, by default,
|
|
106
|
-
* using an infinite region radius and {@link DIST_SQ3} distance metric.
|
|
107
|
-
*
|
|
108
|
-
* @param p -
|
|
109
|
-
* @param r -
|
|
110
|
-
* @param dist -
|
|
111
|
-
*/
|
|
112
|
-
export const radial3 = (p, r, dist = DIST_SQ3) => new Radial(dist, p, r);
|
|
113
|
-
/**
|
|
114
|
-
* Defines a {@link Radial} instance for numeric positions and, by default,
|
|
115
|
-
* using an infinite region radius and {@link DIST_SQ1} distance metric.
|
|
116
|
-
*
|
|
117
|
-
* @param p -
|
|
118
|
-
* @param r -
|
|
119
|
-
* @param dist -
|
|
120
|
-
*/
|
|
121
|
-
export const radialN = (p, r, dist = DIST_SQ1) => new Radial(dist, p, r);
|
|
69
|
+
const radial = (p, r, dist = DIST_SQ) => new Radial(dist, p, r);
|
|
70
|
+
const radial2 = (p, r, dist = DIST_SQ2) => new Radial(dist, p, r);
|
|
71
|
+
const radial3 = (p, r, dist = DIST_SQ3) => new Radial(dist, p, r);
|
|
72
|
+
const radialN = (p, r, dist = DIST_SQ1) => new Radial(dist, p, r);
|
|
73
|
+
export {
|
|
74
|
+
Radial,
|
|
75
|
+
radial,
|
|
76
|
+
radial2,
|
|
77
|
+
radial3,
|
|
78
|
+
radialN
|
|
79
|
+
};
|
package/squared.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { distSq, distSq2, distSq3 } from "@thi.ng/vectors/distsq";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
2
|
+
class Squared {
|
|
3
|
+
constructor(metric) {
|
|
4
|
+
this.metric = metric;
|
|
5
|
+
}
|
|
6
|
+
to(x) {
|
|
7
|
+
return x * x;
|
|
8
|
+
}
|
|
9
|
+
from(x) {
|
|
10
|
+
return Math.sqrt(x);
|
|
11
|
+
}
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const DIST_SQ = new Squared(distSq);
|
|
14
|
+
const DIST_SQ1 = new Squared((a, b) => (a - b) ** 2);
|
|
15
|
+
const DIST_SQ2 = new Squared(distSq2);
|
|
16
|
+
const DIST_SQ3 = new Squared(distSq3);
|
|
17
|
+
export {
|
|
18
|
+
DIST_SQ,
|
|
19
|
+
DIST_SQ1,
|
|
20
|
+
DIST_SQ2,
|
|
21
|
+
DIST_SQ3,
|
|
22
|
+
Squared
|
|
23
|
+
};
|