UNPKG

@equinor/esv-intersection

Version:

Intersection component package with testing and automatic documentation.

60 lines (56 loc) 2.25 kB
import Vector2 from '@equinor/videx-vector2'; import { Vector } from 'curve-interpolator/dist/src/core/interfaces'; type fx = (n: number) => Vector; /* * Methods for calculating length of a curve */ export class ArcLength { /** * Calculate using an adaptive bisect method * @param {Number} func Curve function returning [x,y] * @param {Number} minLimit Min limit * @param {Number} maxLimit Max limit * @param {Number} tolerance Result tolerance * @param {Number} minDepth Min recursive depth before accepting solution * @param {Number} maxDepth Max recursive depth */ static bisect(func: fx, minLimit = 0, maxLimit = 1, tolerance = 0.005, minDepth = 4, maxDepth = 10): number { const calcRec = (a: number, b: number, aVal: number[], bVal: number[], span: number, tolerance: number, depth = 0): number => { const mid = (a + b) / 2; const midVal = func(mid) as number[]; const spanA = Vector2.distance(aVal, midVal); const spanB = Vector2.distance(midVal, bVal); const length = spanA + spanB; if ((depth >= minDepth && Math.abs(length - span) < tolerance) || depth >= maxDepth) { return length; } const tol = tolerance / 2; const d = depth + 1; return calcRec(a, mid, aVal, midVal, spanA, tol, d) + calcRec(mid, b, midVal, bVal, spanB, tol, d); }; const aVal = func(minLimit) as number[]; const bVal = func(maxLimit) as number[]; const span = Vector2.distance(aVal, bVal); const res = calcRec(minLimit, maxLimit, aVal, bVal, span, tolerance); return res; } /** * Calculate using trapezoid method * @param {Number} func Curve function returning [x,y] * @param {Number} minLimit Min limit * @param {Number} maxLimit Max limit * @param {Number} segments Number of segments */ static trapezoid(func: fx, minLimit = 0, maxLimit = 1, segments = 1000): number { let length = 0; let lastPos = func(minLimit) as number[]; const step = (maxLimit - minLimit) / (segments - 1); for (let i = 1; i < segments; i++) { const pos = func(minLimit + i * step) as number[]; const delta = Vector2.distance(lastPos, pos); length += delta; lastPos = pos; } return length; } }