@thi.ng/ramp 2.1.88 → 2.1.89
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/api.js +0 -1
- package/aramp.js +70 -71
- package/hermite.js +42 -31
- package/linear.js +22 -20
- package/package.json +11 -8
package/CHANGELOG.md
CHANGED
package/api.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/aramp.js
CHANGED
|
@@ -2,80 +2,79 @@ import { binarySearch } from "@thi.ng/arrays/binary-search";
|
|
|
2
2
|
import { compareNumAsc } from "@thi.ng/compare/numeric";
|
|
3
3
|
import { absDiff } from "@thi.ng/math/abs";
|
|
4
4
|
import { clamp } from "@thi.ng/math/interval";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
class ARamp {
|
|
6
|
+
stops;
|
|
7
|
+
constructor(stops = [
|
|
8
|
+
[0, 0],
|
|
9
|
+
[1, 1]
|
|
10
|
+
]) {
|
|
11
|
+
this.stops = stops;
|
|
12
|
+
}
|
|
13
|
+
bounds() {
|
|
14
|
+
const stops = this.stops;
|
|
15
|
+
const n = stops.length;
|
|
16
|
+
if (!n)
|
|
17
|
+
return { min: 0, max: 0, minT: 0, maxT: 0 };
|
|
18
|
+
let min = Infinity;
|
|
19
|
+
let max = -Infinity;
|
|
20
|
+
for (let i = n; i-- > 0; ) {
|
|
21
|
+
const y = stops[i][1];
|
|
22
|
+
min = Math.min(min, y);
|
|
23
|
+
max = Math.max(max, y);
|
|
12
24
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
for (let i = n; i-- > 0;) {
|
|
21
|
-
const y = stops[i][1];
|
|
22
|
-
min = Math.min(min, y);
|
|
23
|
-
max = Math.max(max, y);
|
|
24
|
-
}
|
|
25
|
-
return { min, max, minT: stops[0][0], maxT: stops[n - 1][0] };
|
|
25
|
+
return { min, max, minT: stops[0][0], maxT: stops[n - 1][0] };
|
|
26
|
+
}
|
|
27
|
+
addStopAt(t, y, eps = 0.01) {
|
|
28
|
+
if (this.closestIndex(t, eps) !== -1) {
|
|
29
|
+
this.stops.push([t, y]);
|
|
30
|
+
this.sort();
|
|
31
|
+
return true;
|
|
26
32
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
removeStopAt(t, eps = 0.01) {
|
|
36
|
+
if (this.stops.length > 2) {
|
|
37
|
+
const i = this.closestIndex(t, eps);
|
|
38
|
+
if (i !== -1) {
|
|
39
|
+
this.stops.splice(i, 1);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
closestIndex(t, eps = 0.01) {
|
|
46
|
+
const stops = this.stops;
|
|
47
|
+
for (let i = stops.length; i-- > 0; ) {
|
|
48
|
+
if (absDiff(t, stops[i][0]) < eps)
|
|
49
|
+
return i;
|
|
44
50
|
}
|
|
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
|
-
timeIndex(t) {
|
|
70
|
-
const stops = this.stops;
|
|
71
|
-
const n = stops.length;
|
|
72
|
-
if (n < 256) {
|
|
73
|
-
for (let i = n; i-- > 0;) {
|
|
74
|
-
if (t >= stops[i][0])
|
|
75
|
-
return i;
|
|
76
|
-
}
|
|
77
|
-
return -1;
|
|
78
|
-
}
|
|
79
|
-
return binarySearch(stops, [t], (x) => x[0], compareNumAsc);
|
|
51
|
+
return -1;
|
|
52
|
+
}
|
|
53
|
+
clampedIndexTime(i, t, eps = 0.01) {
|
|
54
|
+
const stops = this.stops;
|
|
55
|
+
const n = stops.length - 1;
|
|
56
|
+
return i == 0 ? Math.min(t, stops[1][0] - eps) : i === n ? Math.max(t, stops[n - 1][0] + eps) : clamp(t, stops[i - 1][0] + eps, stops[i + 1][0] - eps);
|
|
57
|
+
}
|
|
58
|
+
sort() {
|
|
59
|
+
this.stops.sort((a, b) => a[0] - b[0]);
|
|
60
|
+
}
|
|
61
|
+
uniform() {
|
|
62
|
+
const n = this.stops.length - 1;
|
|
63
|
+
this.stops.forEach((p, i) => p[0] = i / n);
|
|
64
|
+
}
|
|
65
|
+
timeIndex(t) {
|
|
66
|
+
const stops = this.stops;
|
|
67
|
+
const n = stops.length;
|
|
68
|
+
if (n < 256) {
|
|
69
|
+
for (let i = n; i-- > 0; ) {
|
|
70
|
+
if (t >= stops[i][0])
|
|
71
|
+
return i;
|
|
72
|
+
}
|
|
73
|
+
return -1;
|
|
80
74
|
}
|
|
75
|
+
return binarySearch(stops, [t], (x) => x[0], compareNumAsc);
|
|
76
|
+
}
|
|
81
77
|
}
|
|
78
|
+
export {
|
|
79
|
+
ARamp
|
|
80
|
+
};
|
package/hermite.js
CHANGED
|
@@ -8,36 +8,47 @@ import { mapcat } from "@thi.ng/transducers/mapcat";
|
|
|
8
8
|
import { normRange } from "@thi.ng/transducers/norm-range";
|
|
9
9
|
import { partition } from "@thi.ng/transducers/partition";
|
|
10
10
|
import { ARamp } from "./aramp.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const t2 = tangentCardinal(by, d[1], 0, bx, d[0]);
|
|
30
|
-
return mixCubicHermite(by, t1, cy, t2, norm(t, bx, cx));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
interpolatedPoints(res = 20) {
|
|
34
|
-
return iterator(comp(partition(4, 1), mapcat(([a, [bx, by], [cx, cy], d]) => {
|
|
35
|
-
const t1 = tangentCardinal(a[1], cy, 0, a[0], cx);
|
|
36
|
-
const t2 = tangentCardinal(by, d[1], 0, bx, d[0]);
|
|
37
|
-
return map((t) => [
|
|
38
|
-
mix(bx, cx, t),
|
|
39
|
-
mixCubicHermite(by, t1, cy, t2, t),
|
|
40
|
-
], normRange(res, false));
|
|
41
|
-
})), extendSides(this.stops, 1, 2));
|
|
11
|
+
const hermite = (stops) => new HermiteRamp(stops);
|
|
12
|
+
class HermiteRamp extends ARamp {
|
|
13
|
+
at(t) {
|
|
14
|
+
const stops = this.stops;
|
|
15
|
+
const n = stops.length - 1;
|
|
16
|
+
const i = this.timeIndex(t);
|
|
17
|
+
if (i < 0) {
|
|
18
|
+
return stops[0][1];
|
|
19
|
+
} else if (i >= n) {
|
|
20
|
+
return stops[n][1];
|
|
21
|
+
} else {
|
|
22
|
+
const a = stops[Math.max(i - 1, 0)];
|
|
23
|
+
const [bx, by] = stops[Math.max(i, 0)];
|
|
24
|
+
const [cx, cy] = stops[Math.min(i + 1, n)];
|
|
25
|
+
const d = stops[Math.min(i + 2, n)];
|
|
26
|
+
const t1 = tangentCardinal(a[1], cy, 0, a[0], cx);
|
|
27
|
+
const t2 = tangentCardinal(by, d[1], 0, bx, d[0]);
|
|
28
|
+
return mixCubicHermite(by, t1, cy, t2, norm(t, bx, cx));
|
|
42
29
|
}
|
|
30
|
+
}
|
|
31
|
+
interpolatedPoints(res = 20) {
|
|
32
|
+
return iterator(
|
|
33
|
+
comp(
|
|
34
|
+
partition(4, 1),
|
|
35
|
+
mapcat(([a, [bx, by], [cx, cy], d]) => {
|
|
36
|
+
const t1 = tangentCardinal(a[1], cy, 0, a[0], cx);
|
|
37
|
+
const t2 = tangentCardinal(by, d[1], 0, bx, d[0]);
|
|
38
|
+
return map(
|
|
39
|
+
(t) => [
|
|
40
|
+
mix(bx, cx, t),
|
|
41
|
+
mixCubicHermite(by, t1, cy, t2, t)
|
|
42
|
+
],
|
|
43
|
+
normRange(res, false)
|
|
44
|
+
);
|
|
45
|
+
})
|
|
46
|
+
),
|
|
47
|
+
extendSides(this.stops, 1, 2)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
43
50
|
}
|
|
51
|
+
export {
|
|
52
|
+
HermiteRamp,
|
|
53
|
+
hermite
|
|
54
|
+
};
|
package/linear.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { fit } from "@thi.ng/math/fit";
|
|
2
2
|
import { ARamp } from "./aramp.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const b = stops[i + 1];
|
|
18
|
-
return fit(t, a[0], b[0], a[1], b[1]);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
interpolatedPoints() {
|
|
22
|
-
return this.stops;
|
|
3
|
+
const linear = (stops) => new LinearRamp(stops);
|
|
4
|
+
class LinearRamp extends ARamp {
|
|
5
|
+
at(t) {
|
|
6
|
+
const stops = this.stops;
|
|
7
|
+
const n = stops.length - 1;
|
|
8
|
+
const i = this.timeIndex(t);
|
|
9
|
+
if (i < 0) {
|
|
10
|
+
return stops[0][1];
|
|
11
|
+
} else if (i >= n) {
|
|
12
|
+
return stops[n][1];
|
|
13
|
+
} else {
|
|
14
|
+
const a = stops[i];
|
|
15
|
+
const b = stops[i + 1];
|
|
16
|
+
return fit(t, a[0], b[0], a[1], b[1]);
|
|
23
17
|
}
|
|
18
|
+
}
|
|
19
|
+
interpolatedPoints() {
|
|
20
|
+
return this.stops;
|
|
21
|
+
}
|
|
24
22
|
}
|
|
23
|
+
export {
|
|
24
|
+
LinearRamp,
|
|
25
|
+
linear
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/ramp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.89",
|
|
4
4
|
"description": "Parametric (non-)linearly interpolated 1D lookup tables for remapping values",
|
|
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,14 +35,15 @@
|
|
|
33
35
|
"test": "bun test"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@thi.ng/arrays": "^2.7.
|
|
37
|
-
"@thi.ng/compare": "^2.2.
|
|
38
|
-
"@thi.ng/math": "^5.7.
|
|
39
|
-
"@thi.ng/transducers": "^8.8.
|
|
40
|
-
"@thi.ng/vectors": "^7.8.
|
|
38
|
+
"@thi.ng/arrays": "^2.7.8",
|
|
39
|
+
"@thi.ng/compare": "^2.2.8",
|
|
40
|
+
"@thi.ng/math": "^5.7.7",
|
|
41
|
+
"@thi.ng/transducers": "^8.8.15",
|
|
42
|
+
"@thi.ng/vectors": "^7.8.9"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@microsoft/api-extractor": "^7.38.3",
|
|
46
|
+
"esbuild": "^0.19.8",
|
|
44
47
|
"rimraf": "^5.0.5",
|
|
45
48
|
"tools": "^0.0.1",
|
|
46
49
|
"typedoc": "^0.25.4",
|
|
@@ -92,5 +95,5 @@
|
|
|
92
95
|
"thi.ng": {
|
|
93
96
|
"year": 2019
|
|
94
97
|
},
|
|
95
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
|
|
96
99
|
}
|