diff --git a/src/shapes/composed/axes.ts b/src/shapes/composed/axes.ts index 082c8b8..2c5c4d6 100644 --- a/src/shapes/composed/axes.ts +++ b/src/shapes/composed/axes.ts @@ -215,9 +215,14 @@ class Axes extends ComposedShape { return new PointShape({ points }); } - point(x: number, y: number): Point { - // const [oX, oY] = this.origin(); - // return [x + oX, y + oY]; + point(x: number, y: number): Point; + point(p: Point): Point; + point(xOrPt: number | Point, maybeY?: number): Point { + let [x, y] = Array.isArray(xOrPt) ? xOrPt : [xOrPt, maybeY]; + + if (y === undefined) { + throw new Error('Invalid arguments. Y value must be provided'); + } return [ // math.remap(this._xRange[0], this._xRange[1], -this._xLength / 2, this._xLength / 2, x), diff --git a/src/shapes/primitives/line.ts b/src/shapes/primitives/line.ts index 545db09..4ad38d8 100644 --- a/src/shapes/primitives/line.ts +++ b/src/shapes/primitives/line.ts @@ -3,6 +3,7 @@ import { RGBA } from '@/colors'; import { Locatable, ShapeStyles, isLocatable, locatableToPoint } from '@/shapes/shape'; import { PointShape } from '@/shapes/primitives/point_shape'; import utils from '@/utils'; +import math from '@/math'; type LineCap = 'butt' | 'round' | 'square'; @@ -14,7 +15,7 @@ class Line extends PointShape { constructor(from: Locatable, to: Locatable); constructor(args: { from?: Locatable; to?: Locatable; } & Prettify); - constructor(from: Locatable | { from?: Locatable; to?: Locatable; } & Prettify, to?: Locatable) { + constructor(from: Locatable | { from?: Locatable; to?: Locatable; length?: number } & Prettify, to?: Locatable) { if (isLocatable(from) && isLocatable(to)) { super({ points: Line.fromPoints(from, to) }); } else if (typeof from === 'object' && !Array.isArray(from) && 'from' in from && to === undefined) { @@ -22,7 +23,7 @@ class Line extends PointShape { const _from = from.from || [-1, 0]; const _to = from.to || [1, 0]; - super({ points: Line.fromPoints(_from, _to), ...styles }); + super({ points: Line.fromPoints(_from, _to, from.length), ...styles }); if (styles.lineCap) { this._lineCap = styles.lineCap; @@ -43,8 +44,28 @@ class Line extends PointShape { return this._lineCap; } - private static fromPoints(from: Locatable, to: Locatable): Point[] { - return [locatableToPoint(from), locatableToPoint(to)]; + private static fromPoints(from: Locatable, to: Locatable, length?: number): Point[] { + if (length === undefined) { + return [locatableToPoint(from), locatableToPoint(to)]; + } else { + const [fx, fy] = locatableToPoint(from); + const [tx, ty] = locatableToPoint(to); + + const [mx, my] = math.midpoint([fx, fy], [tx, ty]); + const [ux, uy] = math.unitVec([fx, fy], [tx, ty]); + + const fromPt = [ + mx - ux * length / 2, + my - uy * length / 2 + ] as Point; + + const toPt = [ + mx + ux * length / 2, + my + uy * length / 2 + ] as Point; + + return [fromPt, toPt]; + } } } diff --git a/test/script_test.ts b/test/script_test.ts index f73746a..3dec922 100644 --- a/test/script_test.ts +++ b/test/script_test.ts @@ -308,6 +308,34 @@ class TestScene extends Scene { // this.add(new Dot(shape.center())); // console.log(shape.center()); + // const axes = new Axes({ + // xLength: 8, + // yLength: 6, + // xRange: [0, 1], + // xStep: 0.25, + // yRange: [0, 35], + // yStep: 5, + // xLabel: 'time (h)', + // yLabel: 'distance (miles)' + // }); + + // const p = axes.plot(x => 25 * x * x).changeLineColor(Colors.green()); + + // this.add(axes, p); + + // const p1 = axes.point(0.25, 1.5625); + // const p2 = axes.point(0.5, 6.25); + // const p3 = axes.point(0.75, 14.0625); + // const p4 = axes.point(1, 25); + + // this.add( + // new TangentLine({ plot: p, x: 0.5, length: 4, color: Colors.pink() }), + // new Dot({ center: p1, color: Colors.green() }), + // new Dot({ center: p2, color: Colors.green() }), + // new Dot({ center: p3, color: Colors.green() }), + // new Dot({ center: p4, color: Colors.green() }), + // ); + const axes = new Axes({ xLength: 8, yLength: 6, @@ -318,22 +346,29 @@ class TestScene extends Scene { xLabel: 'time (h)', yLabel: 'distance (miles)' }); - + const p = axes.plot(x => 25 * x * x).changeLineColor(Colors.green()); - - this.add(axes, p); - + const p1 = axes.point(0.25, 1.5625); const p2 = axes.point(0.5, 6.25); const p3 = axes.point(0.75, 14.0625); const p4 = axes.point(1, 25); - + + const pText = new Text({ text: 'P' }).nextTo(p2, UP(), 0.3); + const qText = new Text({ text: 'Q' }).nextTo(p3, UP(), 0.3); + this.add( + axes, p, new TangentLine({ plot: p, x: 0.5, length: 4, color: Colors.pink() }), + new Line({ from: p2, to: p3, length: 5, lineColor: Colors.blue() }), + new Dot({ center: p1, color: Colors.green() }), - new Dot({ center: p2, color: Colors.green() }), + new Dot({ center: p2, color: Colors.pink() }), new Dot({ center: p3, color: Colors.green() }), new Dot({ center: p4, color: Colors.green() }), + + new Dot({ center: p3, color: Colors.blue() }), + pText, qText ); } }