@rdme/curve-2d
Version:
2d curves in typescript
83 lines (70 loc) • 2.52 kB
text/typescript
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;
}
}