diff --git a/src/state/states/EditTrackState.ts b/src/state/states/EditTrackState.ts index 00c3fd3..b6f394a 100644 --- a/src/state/states/EditTrackState.ts +++ b/src/state/states/EditTrackState.ts @@ -42,18 +42,6 @@ export class EditTrackState extends State { const track = getContextItem("track"); const doodler = getContextItem("doodler"); - // For moving a segment, i.e. the currently active one - // const segment = track.lastSegment; - // if (segment) { - // const firstPoint = segment.points[0].copy(); - // const { x, y } = inputManager.getMouseLocation(); - // segment.points.forEach((p, i) => { - // const relativePoint = Vector.sub(p, firstPoint); - // p.set(x, y); - // p.add(relativePoint); - // }); - // } - if (this.selectedSegment) { const segment = this.selectedSegment; const firstPoint = segment.points[0].copy(); diff --git a/src/track/system.ts b/src/track/system.ts index 33e4a7a..d3eda77 100644 --- a/src/track/system.ts +++ b/src/track/system.ts @@ -282,12 +282,54 @@ export class TrackSegment extends PathSegment { antiNormalPoints: Vector[] = []; evenPoints: [Vector, number][] = []; + aabb!: AABB; + + private trackGuage = 12; + constructor(p: VectorSet, id?: string) { super(p); this.doodler = getContextItem("doodler"); this.id = id ?? crypto.randomUUID(); this.recalculateRailPoints(); this.recalculateTiePoints(); + this.updateAABB(); + } + + updateAABB() { + let minX = Infinity; + let maxX = -Infinity; + let minY = Infinity; + let maxY = -Infinity; + + this.points.forEach((p) => { + minX = Math.min(minX, p.x); + maxX = Math.max(maxX, p.x); + minY = Math.min(minY, p.y); + maxY = Math.max(maxY, p.y); + }); + + const width = maxX - minX; + const height = maxY - minY; + if (width < this.trackGuage) { + const extra = (this.trackGuage - width) / 2; + minX -= extra; + maxX += extra; + } + if (height < this.trackGuage) { + const extra = (this.trackGuage - height) / 2; + minY -= extra; + maxY += extra; + } + this.aabb = { + pos: new Vector(minX, minY), + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY, + center: new Vector(minX, minY).add( + new Vector(maxX - minX, maxY - minY).div(2), + ), + }; } recalculateRailPoints(resolution = 60) { @@ -296,7 +338,7 @@ export class TrackSegment extends PathSegment { for (let i = 0; i <= resolution; i++) { const t = i / resolution; const normal = this.tangent(t).rotate(Math.PI / 2); - normal.setMag(6); + normal.setMag(this.trackGuage / 2); const p = this.getPointAtT(t); this.normalPoints.push(p.copy().add(normal)); this.antiNormalPoints.push(p.copy().add(normal.rotate(Math.PI))); @@ -389,6 +431,13 @@ export class TrackSegment extends PathSegment { // color: "red", // weight: 3, // }); + + this.doodler.drawRect(this.aabb.pos, this.aabb.width, this.aabb.height, { + color: "lime", + }); + this.doodler.drawCircle(this.aabb.center, 2, { + color: "cyan", + }); } serialize(): SerializedTrackSegment { diff --git a/src/train/train.ts b/src/train/train.ts index e3e8988..5431bc6 100644 --- a/src/train/train.ts +++ b/src/train/train.ts @@ -4,15 +4,6 @@ import { Spline, TrackSegment, TrackSystem } from "../track/system.ts"; import { Debuggable } from "../lib/debuggable.ts"; import { lerp, lerpAngle, map } from "../math/lerp.ts"; -type TrainAABB = { - pos: Vector; - x: number; - y: number; - width: number; - height: number; - center: Vector; -}; - export class Train extends Debuggable { nodes: Vector[] = []; @@ -25,7 +16,7 @@ export class Train extends Debuggable { speed = 5; - aabb!: TrainAABB; + aabb!: AABB; get segments() { return Array.from( @@ -204,7 +195,7 @@ export class TrainCar extends Debuggable { train?: Train; - aabb!: TrainAABB; + aabb!: AABB; constructor( length: number, diff --git a/src/types.ts b/src/types.ts index 35e6d08..b2a3f34 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,4 +25,25 @@ declare global { angles: boolean; aabb: boolean; }; + + type AABB = { + pos: Vector; + x: number; + y: number; + width: number; + height: number; + center: Vector; + }; +} + +export function applyMixins(derivedCtor: any, baseCtors: any[]) { + baseCtors.forEach((baseCtor) => { + Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => { + Object.defineProperty( + derivedCtor.prototype, + name, + Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ?? {}, + ); + }); + }); }