98 lines
2.2 KiB
TypeScript
98 lines
2.2 KiB
TypeScript
export function logSpace(xMin: number, xMax: number, steps: number): number[] {
|
|
const logMin = Math.log10(xMin);
|
|
const logMax = Math.log10(xMax);
|
|
const out: number[] = [];
|
|
for (let s = 0; s <= steps; s++) {
|
|
out.push(Math.pow(10, logMin + ((logMax - logMin) * s) / steps));
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export type CurvePoint = { x: number; y: number };
|
|
|
|
export type CurveColors = {
|
|
strokeColor: string;
|
|
fillAbove: string;
|
|
fillAboveFade: string;
|
|
fillBelowFade: string;
|
|
fillBelow: string;
|
|
};
|
|
|
|
export const DEFAULT_CURVE_COLORS: CurveColors = {
|
|
strokeColor: '#e5e7eb',
|
|
fillAbove: 'rgba(74, 222, 128, 0.35)',
|
|
fillAboveFade: 'rgba(74, 222, 128, 0.08)',
|
|
fillBelowFade: 'rgba(248, 113, 113, 0.08)',
|
|
fillBelow: 'rgba(248, 113, 113, 0.35)',
|
|
};
|
|
|
|
export type CurveStyle = {
|
|
strokeColor?: string;
|
|
fillColors?: CurveColors;
|
|
/** Draw the area fill under/around the curve. Defaults to true. */
|
|
fill?: boolean;
|
|
lineWidth?: number;
|
|
dimmed?: boolean;
|
|
};
|
|
|
|
/** A single polyline ready to be handed to `drawCurves`. */
|
|
export type Curve = {
|
|
points: CurvePoint[];
|
|
style?: CurveStyle;
|
|
};
|
|
|
|
export function sumCurvePoints(pointArrays: CurvePoint[][]): CurvePoint[] {
|
|
if (pointArrays.length === 0) return [];
|
|
|
|
const length = pointArrays[0].length;
|
|
const result: CurvePoint[] = new Array(length);
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
let y = 0;
|
|
for (const points of pointArrays) {
|
|
y += points[i]?.y ?? 0;
|
|
}
|
|
result[i] = { x: pointArrays[0][i].x, y };
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function sumPhaseCurvePoints(pointArrays: CurvePoint[][]): CurvePoint[] {
|
|
if (pointArrays.length === 0) return [];
|
|
|
|
const length = pointArrays[0].length;
|
|
const result: CurvePoint[] = new Array(length);
|
|
|
|
let previousPhase = 0;
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
let phase = 0;
|
|
|
|
for (const points of pointArrays) {
|
|
phase += points[i]?.y ?? 0;
|
|
}
|
|
|
|
// Keep phase continuous while summing.
|
|
while (phase - previousPhase > 180) {
|
|
phase -= 360;
|
|
}
|
|
|
|
while (phase - previousPhase < -180) {
|
|
phase += 360;
|
|
}
|
|
|
|
// Wrap to [-180, 180].
|
|
const wrapped = ((((phase + 180) % 360) + 360) % 360) - 180;
|
|
|
|
result[i] = {
|
|
x: pointArrays[0][i].x,
|
|
y: wrapped,
|
|
};
|
|
|
|
previousPhase = phase;
|
|
}
|
|
|
|
return result;
|
|
}
|