UNPKG

@rdme/curve-2d

Version:

2d curves in typescript

83 lines (70 loc) 2.52 kB
import { CurveBase2d } from "src/curve-base2d"; import { Vec2d, Vec2dLike } from "src/vec2d"; const { floor } = Math; export class PolyCurve2d<T extends CurveBase2d> extends CurveBase2d { protected _curves: T[]; constructor(curves: T[]) { super(); this._curves = curves.map((curve) => curve.clone()) as T[]; } public clone(): this { return this._applyClone(new PolyCurve2d(this._curves) as this); } public get(t: number): Vec2d { const [curve, offset] = this._curveAndOffset(t); return curve.get(offset); } public getSegment(tStart: number, tEnd: number): CurveBase2d { if (tStart === tEnd) { const [curve, offset] = this._curveAndOffset(tStart); return curve.getSegment(offset, offset); } if (tStart === 0 && tEnd === 1) return this.clone(); if (tStart > tEnd) return this.getSegment(tEnd, tStart).reverse(); const [curveStart, offsetStart, indexStart] = this._curveAndOffset(tStart); const [curveEnd, offsetEnd, indexEnd] = this._curveAndOffset(tStart); if (indexStart === indexEnd) return curveStart.getSegment(offsetStart, offsetEnd); return new PolyCurve2d([ curveStart.getSegment(offsetStart, 1), ...this._curves .slice(indexStart + 1, indexEnd - 1) .map((curve) => curve.clone()), curveEnd.getSegment(0, offsetEnd), ]); } protected _curveAndOffset( t: number ): [curve: T, offset: number, index: number] { const { _curves } = this; if (t === 0) return [_curves[0], 0, 0]; if (t === 1) return [_curves[_curves.length - 1], 1, _curves.length - 1]; const index = floor(t * _curves.length); return [_curves[index], t * _curves.length - index, index]; } protected _applyReverse(curve: this): this { super._applyReverse(curve); curve._curves = curve._curves.map((curve) => curve.reverse()); return curve; } public reverse(): this { return new PolyCurve2d( this._curves.map((curve) => curve.reverse()).reverse() ) as this; } public scale(factor: number, origin?: Vec2dLike): this { return new PolyCurve2d( this._curves.map((curve) => curve.scale(factor, origin)) ) as this; } public rotate(angle: number, origin?: Vec2dLike): this { return new PolyCurve2d( this._curves.map((curve) => curve.rotate(angle, origin)) ) as this; } public translate(vector: Vec2dLike): this { return new PolyCurve2d( this._curves.map((curve) => curve.translate(vector)) ) as this; } }