just so much groundwork

This commit is contained in:
2025-02-05 04:00:40 -07:00
parent b3772052f5
commit 952b5dd57f
22 changed files with 1003 additions and 2081 deletions

View File

@@ -1,8 +1,11 @@
import { Vector } from "doodler";
export const lerp = (a: number, b: number, t: number) => {
return (a*t) + (b*(1-t));
}
return (a * t) + (b * (1 - t));
};
export const map = (value: number, x1: number, y1: number, x2: number, y2: number) =>
(value - x1) * (y2 - x2) / (y1 - x1) + x2;
export const map = (
value: number,
x1: number,
y1: number,
x2: number,
y2: number,
) => (value - x1) * (y2 - x2) / (y1 - x1) + x2;

View File

@@ -1,7 +1,6 @@
import { Vector } from "doodler";
import { Vector } from "@bearmetal/doodler";
export class ComplexPath {
points: Vector[] = [];
radius = 50;
@@ -22,10 +21,10 @@ export class ComplexPath {
ctx.save();
ctx.lineWidth = 2;
ctx.strokeStyle = 'white';
ctx.setLineDash([21, 6])
ctx.strokeStyle = "white";
ctx.setLineDash([21, 6]);
let last = this.points[this.points.length - 1]
let last = this.points[this.points.length - 1];
for (const point of this.points) {
ctx.beginPath();
@@ -39,8 +38,7 @@ export class ComplexPath {
}
export class PathSegment {
points: [Vector, Vector, Vector, Vector]
ctx?: CanvasRenderingContext2D;
points: [Vector, Vector, Vector, Vector];
length: number;
@@ -49,44 +47,23 @@ export class PathSegment {
this.length = this.calculateApproxLength(100);
}
setContext(ctx: CanvasRenderingContext2D) {
this.ctx = ctx;
}
draw() {
const [a, b, c, d] = this.points;
doodler.drawBezier(a, b, c, d, {
strokeColor: '#ffffff50'
})
// if (!this.ctx) return;
// const ctx = this.ctx;
// ctx.save();
// ctx.beginPath();
// ctx.moveTo(this.points[0].x, this.points[0].y);
// ctx.bezierCurveTo(
// this.points[1].x,
// this.points[1].y,
// this.points[2].x,
// this.points[2].y,
// this.points[3].x,
// this.points[3].y,
// );
// ctx.strokeStyle = '#ffffff50';
// ctx.lineWidth = 2;
// ctx.stroke();
// ctx.restore();
}
getPointAtT(t: number) {
const [a, b, c, d] = this.points;
const res = a.copy();
res.add(Vector.add(a.copy().mult(-3), b.copy().mult(3)).mult(t))
res.add(Vector.add(Vector.add(a.copy().mult(3), b.copy().mult(-6)), c.copy().mult(3)).mult(Math.pow(t, 2)));
res.add(Vector.add(Vector.add(a.copy().mult(-1), b.copy().mult(3)), Vector.add(c.copy().mult(-3), d.copy())).mult(Math.pow(t, 3)));
res.add(Vector.add(a.copy().mult(-3), b.copy().mult(3)).mult(t));
res.add(
Vector.add(
Vector.add(a.copy().mult(3), b.copy().mult(-6)),
c.copy().mult(3),
).mult(Math.pow(t, 2)),
);
res.add(
Vector.add(
Vector.add(a.copy().mult(-1), b.copy().mult(3)),
Vector.add(c.copy().mult(-3), d.copy()),
).mult(Math.pow(t, 3)),
);
return res;
}
@@ -123,15 +100,20 @@ export class PathSegment {
points.push([i * resolution, this]);
}
}
return points
return points;
}
tangent(t: number) {
// dP(t) / dt = -3(1-t)^2 * P0 + 3(1-t)^2 * P1 - 6t(1-t) * P1 - 3t^2 * P2 + 6t(1-t) * P2 + 3t^2 * P3
// dP(t) / dt = -3(1-t)^2 * P0 + 3(1-t)^2 * P1 - 6t(1-t) * P1 - 3t^2 * P2 + 6t(1-t) * P2 + 3t^2 * P3
const [a, b, c, d] = this.points;
const res = Vector.sub(b, a).mult(3 * Math.pow(1 - t, 2));
res.add(Vector.add(Vector.sub(c, b).mult(6 * (1 - t) * t), Vector.sub(d, c).mult(3 * Math.pow(t, 2))));
res.add(
Vector.add(
Vector.sub(c, b).mult(6 * (1 - t) * t),
Vector.sub(d, c).mult(3 * Math.pow(t, 2)),
),
);
return res;
}
@@ -158,12 +140,12 @@ export class PathSegment {
let dist;
if (k <= 0.0) {
dist = Vector.hypot2(v, a)
dist = Vector.hypot2(v, a);
} else if (k >= 1.0) {
dist = Vector.hypot2(v, b)
dist = Vector.hypot2(v, b);
}
dist = Vector.hypot2(v, d)
dist = Vector.hypot2(v, d);
if (dist < distance) {
distance = dist;
@@ -179,27 +161,28 @@ export class PathSegment {
calculateApproxLength(resolution = 25) {
const stepSize = 1 / resolution;
const points: Vector[] = []
const points: Vector[] = [];
for (let i = 0; i <= resolution; i++) {
const current = stepSize * i;
points.push(this.getPointAtT(current))
points.push(this.getPointAtT(current));
}
this.length = points.reduce((acc: { prev?: Vector, length: number }, cur) => {
const prev = acc.prev;
acc.prev = cur;
if (!prev) return acc;
acc.length += cur.dist(prev);
return acc;
}, { prev: undefined, length: 0 }).length
this.length =
points.reduce((acc: { prev?: Vector; length: number }, cur) => {
const prev = acc.prev;
acc.prev = cur;
if (!prev) return acc;
acc.length += cur.dist(prev);
return acc;
}, { prev: undefined, length: 0 }).length;
return this.length;
}
calculateEvenlySpacedPoints(spacing: number, resolution = 1) {
const points: Vector[] = []
const points: Vector[] = [];
points.push(this.points[0]);
let prev = points[0];
let distSinceLastEvenPoint = 0
let distSinceLastEvenPoint = 0;
let t = 0;
@@ -209,10 +192,12 @@ export class PathSegment {
const point = this.getPointAtT(t);
distSinceLastEvenPoint += prev.dist(point);
if (distSinceLastEvenPoint >= spacing) {
const overshoot = distSinceLastEvenPoint - spacing;
const evenPoint = Vector.add(point, Vector.sub(point, prev).normalize().mult(overshoot))
const evenPoint = Vector.add(
point,
Vector.sub(point, prev).normalize().mult(overshoot),
);
distSinceLastEvenPoint = overshoot;
points.push(evenPoint);
prev = evenPoint;