From 41612d1320db0fcdd08da9cab550ca2deb3a418f Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Fri, 7 Oct 2022 08:28:24 -0400 Subject: [PATCH] Convert the curve helpers to TS (#10733) * Convert the curve helpers to TS * Remove old type --- .../{helpers.curve.js => helpers.curve.ts} | 75 ++++++++++++------- src/helpers/helpers.interpolation.ts | 4 +- src/helpers/types.ts | 1 + types/helpers/helpers.curve.d.ts | 34 --------- types/helpers/index.d.ts | 1 - 5 files changed, 50 insertions(+), 65 deletions(-) rename src/helpers/{helpers.curve.js => helpers.curve.ts} (74%) delete mode 100644 types/helpers/helpers.curve.d.ts diff --git a/src/helpers/helpers.curve.js b/src/helpers/helpers.curve.ts similarity index 74% rename from src/helpers/helpers.curve.js rename to src/helpers/helpers.curve.ts index 9c42c1dc6..14a6bc332 100644 --- a/src/helpers/helpers.curve.js +++ b/src/helpers/helpers.curve.ts @@ -1,11 +1,35 @@ import {almostEquals, distanceBetweenPoints, sign} from './helpers.math'; import {_isPointInArea} from './helpers.canvas'; +import {ChartArea} from '../../types'; + +export interface SplinePoint { + x: number; + y: number; + skip?: boolean; + + // Both Bezier and monotone interpolations have these fields + // but they are added in different spots + cp1x?: number; + cp1y?: number; + cp2x?: number; + cp2y?: number; +} const EPSILON = Number.EPSILON || 1e-14; -const getPoint = (points, i) => i < points.length && !points[i].skip && points[i]; -const getValueAxis = (indexAxis) => indexAxis === 'x' ? 'y' : 'x'; -export function splineCurve(firstPoint, middlePoint, afterPoint, t) { +type OptionalSplinePoint = SplinePoint | false +const getPoint = (points: SplinePoint[], i: number): OptionalSplinePoint => i < points.length && !points[i].skip && points[i]; +const getValueAxis = (indexAxis: 'x' | 'y') => indexAxis === 'x' ? 'y' : 'x'; + +export function splineCurve( + firstPoint: SplinePoint, + middlePoint: SplinePoint, + afterPoint: SplinePoint, + t: number +): { + previous: SplinePoint + next: SplinePoint + } { // Props to Rob Spencer at scaled innovation for his post on splining between points // http://scaledinnovation.com/analytics/splines/aboutSplines.html @@ -42,10 +66,10 @@ export function splineCurve(firstPoint, middlePoint, afterPoint, t) { /** * Adjust tangents to ensure monotonic properties */ -function monotoneAdjust(points, deltaK, mK) { +function monotoneAdjust(points: SplinePoint[], deltaK: number[], mK: number[]) { const pointsLen = points.length; - let alphaK, betaK, tauK, squaredMagnitude, pointCurrent; + let alphaK: number, betaK: number, tauK: number, squaredMagnitude: number, pointCurrent: OptionalSplinePoint; let pointAfter = getPoint(points, 0); for (let i = 0; i < pointsLen - 1; ++i) { pointCurrent = pointAfter; @@ -72,10 +96,10 @@ function monotoneAdjust(points, deltaK, mK) { } } -function monotoneCompute(points, mK, indexAxis = 'x') { +function monotoneCompute(points: SplinePoint[], mK: number[], indexAxis: 'x' | 'y' = 'x') { const valueAxis = getValueAxis(indexAxis); const pointsLen = points.length; - let delta, pointBefore, pointCurrent; + let delta: number, pointBefore: OptionalSplinePoint, pointCurrent: OptionalSplinePoint; let pointAfter = getPoint(points, 0); for (let i = 0; i < pointsLen; ++i) { @@ -106,26 +130,15 @@ function monotoneCompute(points, mK, indexAxis = 'x') { * but preserves monotonicity of the provided data and ensures no local extremums are added * between the dataset discrete points due to the interpolation. * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - * - * @param {{ - * x: number, - * y: number, - * skip?: boolean, - * cp1x?: number, - * cp1y?: number, - * cp2x?: number, - * cp2y?: number, - * }[]} points - * @param {string} indexAxis */ -export function splineCurveMonotone(points, indexAxis = 'x') { +export function splineCurveMonotone(points: SplinePoint[], indexAxis: 'x' | 'y' = 'x') { const valueAxis = getValueAxis(indexAxis); const pointsLen = points.length; - const deltaK = Array(pointsLen).fill(0); - const mK = Array(pointsLen); + const deltaK: number[] = Array(pointsLen).fill(0); + const mK: number[] = Array(pointsLen); // Calculate slopes (deltaK) and initialize tangents (mK) - let i, pointBefore, pointCurrent; + let i, pointBefore: OptionalSplinePoint, pointCurrent: OptionalSplinePoint; let pointAfter = getPoint(points, 0); for (i = 0; i < pointsLen; ++i) { @@ -144,8 +157,8 @@ export function splineCurveMonotone(points, indexAxis = 'x') { } mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] - : (sign(deltaK[i - 1]) !== sign(deltaK[i])) ? 0 - : (deltaK[i - 1] + deltaK[i]) / 2; + : (sign(deltaK[i - 1]) !== sign(deltaK[i])) ? 0 + : (deltaK[i - 1] + deltaK[i]) / 2; } monotoneAdjust(points, deltaK, mK); @@ -153,11 +166,11 @@ export function splineCurveMonotone(points, indexAxis = 'x') { monotoneCompute(points, mK, indexAxis); } -function capControlPoint(pt, min, max) { +function capControlPoint(pt: number, min: number, max: number) { return Math.max(Math.min(pt, max), min); } -function capBezierPoints(points, area) { +function capBezierPoints(points: SplinePoint[], area: ChartArea) { let i, ilen, point, inArea, inAreaPrev; let inAreaNext = _isPointInArea(points[0], area); for (i = 0, ilen = points.length; i < ilen; ++i) { @@ -182,8 +195,14 @@ function capBezierPoints(points, area) { /** * @private */ -export function _updateBezierControlPoints(points, options, area, loop, indexAxis) { - let i, ilen, point, controlPoints; +export function _updateBezierControlPoints( + points: SplinePoint[], + options, + area: ChartArea, + loop: boolean, + indexAxis: 'x' | 'y' +) { + let i: number, ilen: number, point: SplinePoint, controlPoints: ReturnType; // Only consider points that are drawn in case the spanGaps option is used if (options.spanGaps) { diff --git a/src/helpers/helpers.interpolation.ts b/src/helpers/helpers.interpolation.ts index 9d86528da..81f1948df 100644 --- a/src/helpers/helpers.interpolation.ts +++ b/src/helpers/helpers.interpolation.ts @@ -1,5 +1,5 @@ import type {Point} from '../../types/geometric'; -import type {MonotoneSplinePoint} from '../../types/helpers'; +import type {SplinePoint} from './helpers.curve'; /** * @private @@ -30,7 +30,7 @@ export function _steppedInterpolation( /** * @private */ -export function _bezierInterpolation(p1: MonotoneSplinePoint, p2: MonotoneSplinePoint, t: number, mode?) { // eslint-disable-line @typescript-eslint/no-unused-vars +export function _bezierInterpolation(p1: SplinePoint, p2: SplinePoint, t: number, mode?) { // eslint-disable-line @typescript-eslint/no-unused-vars const cp1 = {x: p1.cp2x, y: p1.cp2y}; const cp2 = {x: p2.cp1x, y: p2.cp1y}; const a = _pointInLine(p1, cp1, t); diff --git a/src/helpers/types.ts b/src/helpers/types.ts index 9806aa54f..2cbf3a04c 100644 --- a/src/helpers/types.ts +++ b/src/helpers/types.ts @@ -7,6 +7,7 @@ export * from './helpers.color'; export * from './helpers.collection'; export * from './helpers.core'; +export * from './helpers.curve'; export * from './helpers.easing'; export * from './helpers.extras'; export * from './helpers.interpolation'; diff --git a/types/helpers/helpers.curve.d.ts b/types/helpers/helpers.curve.d.ts deleted file mode 100644 index 28d9ee4a6..000000000 --- a/types/helpers/helpers.curve.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -export interface SplinePoint { - x: number; - y: number; -} - -/** - * Props to Rob Spencer at scaled innovation for his post on splining between points - * http://scaledinnovation.com/analytics/splines/aboutSplines.html - */ -export function splineCurve( - firstPoint: SplinePoint & { skip?: boolean }, - middlePoint: SplinePoint, - afterPoint: SplinePoint, - t: number -): { - previous: SplinePoint; - next: SplinePoint; -}; - -export interface MonotoneSplinePoint extends SplinePoint { - skip: boolean; - cp1x?: number; - cp1y?: number; - cp2x?: number; - cp2y?: number; -} - -/** - * This function calculates Bézier control points in a similar way than |splineCurve|, - * but preserves monotonicity of the provided data and ensures no local extremums are added - * between the dataset discrete points due to the interpolation. - * @see https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - */ -export function splineCurveMonotone(points: readonly MonotoneSplinePoint[], indexAxis?: 'x' | 'y'): void; diff --git a/types/helpers/index.d.ts b/types/helpers/index.d.ts index 905c0cb0f..68da2dde2 100644 --- a/types/helpers/index.d.ts +++ b/types/helpers/index.d.ts @@ -1,5 +1,4 @@ export * from './helpers.canvas'; -export * from './helpers.curve'; export * from './helpers.dom'; export * from './helpers.options'; export * from './helpers.canvas'; -- 2.47.2