Skip to content

Commit

Permalink
Updatable interpolators (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
smikhalevski authored Feb 12, 2022
1 parent 03bd9a7 commit 5e2b6ca
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 41 deletions.
40 changes: 28 additions & 12 deletions src/main/cspline-monot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {MutableArrayLike} from './shared-types';
import {Interpolator, MutableArrayLike} from './shared-types';
import {binarySearch} from './binary-search';

/**
Expand All @@ -19,18 +19,34 @@ import {binarySearch} from './binary-search';
*
* @see {@link https://en.wikipedia.org/wiki/Monotone_cubic_interpolation Monotone cubic interpolation}
*/
export function csplineMonot(xs: ArrayLike<number>, ys: ArrayLike<number>): (x: number) => number {
const n = Math.min(xs.length, ys.length);
export function csplineMonot(xs: ArrayLike<number>, ys: ArrayLike<number>): Interpolator {
let n = -1;
let splines: MutableArrayLike<number>;

if (n === 0) {
return () => NaN;
}
if (n === 1) {
const y0 = ys[0];
return () => y0;
}
const splines = createCSplinesMonot(xs, ys, n);
return (x) => interpolateCSplineMonot(xs, ys, x, n, splines);
const interp: Interpolator = (x) => {
if (n === 0) {
return NaN;
}
if (n === 1) {
return ys[0];
}
return interpolateCSplineMonot(xs, ys, x, n, splines);
};

interp.update = (nextXs, nextYs) => {
const nextN = Math.min(nextXs.length, nextYs.length);
xs = nextXs;
ys = nextYs;

if (nextN > 1) {
splines = createCSplinesMonot(xs, ys, nextN, n >= nextN ? splines : undefined);
}
n = nextN;
};

interp.update(xs, ys);

return interp;
}

const enum T {
Expand Down
42 changes: 29 additions & 13 deletions src/main/cspline.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {MutableArrayLike} from './shared-types';
import {Interpolator, MutableArrayLike} from './shared-types';
import {binarySearch} from './binary-search';

/**
Expand All @@ -16,18 +16,34 @@ import {binarySearch} from './binary-search';
* @param ys The array of corresponding Y coordinates of pivot points.
* @returns The function that takes X coordinate and returns an interpolated Y coordinate.
*/
export function cspline(xs: ArrayLike<number>, ys: ArrayLike<number>): (x: number) => number {
const n = Math.min(xs.length, ys.length);

if (n === 0) {
return () => NaN;
}
if (n === 1) {
const y0 = ys[0];
return () => y0;
}
const splines = createCSplines(xs, ys, n);
return (x) => interpolateCSpline(xs, ys, x, n, splines);
export function cspline(xs: ArrayLike<number>, ys: ArrayLike<number>): Interpolator {
let n = -1;
let splines: MutableArrayLike<number>;

const interp: Interpolator = (x) => {
if (n === 0) {
return NaN;
}
if (n === 1) {
return ys[0];
}
return interpolateCSpline(xs, ys, x, n, splines);
};

interp.update = (nextXs, nextYs) => {
const nextN = Math.min(nextXs.length, nextYs.length);
xs = nextXs;
ys = nextYs;

if (nextN > 1) {
splines = createCSplines(xs, ys, nextN, n >= nextN ? splines : undefined);
}
n = nextN;
};

interp.update(xs, ys);

return interp;
}

const enum T {
Expand Down
12 changes: 6 additions & 6 deletions src/main/easing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {exp, log} from './math-utils';
/**
* Maps `t` ∈ [0, 1] exponentially to [0, 1].
*
* @param t the value to map.
* @param q greater values produce more bent curve, `f(t, 0) = t`.
* @param t The value to map.
* @param q Greater values produce more bent curve, `f(t, 0) = t`.
*/
export function easeExp(t: number, q = 1): number {
return q === 0 ? t : (exp(q * t) - 1) / (exp(q) - 1);
Expand All @@ -13,11 +13,11 @@ export function easeExp(t: number, q = 1): number {
/**
* Maps `t` ∈ [0, 1] logarithmically to [0, 1].
*
* @param x the value to map.
* @param q greater values produce more bent curve, `f(t, 0) = t`.
* @param t The value to map.
* @param q Greater values produce more bent curve, `f(t, 0) = t`.
*/
export function easeLog(x: number, q = 1): number {
return q === 0 ? x : log(x * (exp(q) - 1) + 1) / q;
export function easeLog(t: number, q = 1): number {
return q === 0 ? t : log(t * (exp(q) - 1) + 1) / q;
}

export function easeInQuad(t: number): number {
Expand Down
27 changes: 17 additions & 10 deletions src/main/lerp.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {binarySearch} from './binary-search';
import {Interpolator} from './shared-types';

/**
* Returns a linear interpolation function for given pivot points.
Expand All @@ -15,17 +16,13 @@ import {binarySearch} from './binary-search';
* @param ys The array of corresponding Y coordinates of pivot points.
* @returns The function that takes X coordinate and returns an interpolated Y coordinate.
*/
export function lerp(xs: ArrayLike<number>, ys: ArrayLike<number>): (x: number) => number {
const n = Math.min(xs.length, ys.length);
export function lerp(xs: ArrayLike<number>, ys: ArrayLike<number>): Interpolator {
let n = -1;

if (n === 0) {
return () => NaN;
}
if (n === 1) {
const y0 = ys[0];
return () => y0;
}
return (x) => {
const interp: Interpolator = (x) => {
if (n === 0) {
return NaN;
}
if (x <= xs[0]) {
return ys[0];
}
Expand All @@ -43,4 +40,14 @@ export function lerp(xs: ArrayLike<number>, ys: ArrayLike<number>): (x: number)

return yj + (x - xj) / (xs[i] - xj) * (ys[i] - yj);
};

interp.update = (nextXs, nextYs) => {
n = Math.min(nextXs.length, nextYs.length);
xs = nextXs;
ys = nextYs;
};

interp.update(xs, ys);

return interp;
}
7 changes: 7 additions & 0 deletions src/main/shared-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
export interface Interpolator {
(x: number): number;

update(xs: ArrayLike<number>, ys: ArrayLike<number>): void;
}

export interface MutableArrayLike<T> {
length: number;

[n: number]: T;
}

0 comments on commit 5e2b6ca

Please sign in to comment.