import { Color } from "./style"; export interface XY { x: number; y: number; } export interface Bounds { left: number, top: number, right: number, bottom: number, } export interface BoundFlags { left: boolean, top: boolean, right: boolean, bottom: boolean, } export function boundFlags(s: string): BoundFlags { return { left: s.indexOf('w') != -1 || s.indexOf('l') != -1, top: s.indexOf('n') != -1 || s.indexOf('t') != -1, right: s.indexOf('e') != -1 || s.indexOf('r') != -1, bottom: s.indexOf('s') != -1 || s.indexOf('b') != -1, }; } export type PartialBounds = Partial; export interface XYFlags { onX?: boolean; onY?: boolean; } export class Vec { constructor(public coord: XY) {} x(val?: number) { if (val != null) this.coord.x = val; return this.coord.x; } y(val?: number) { if (val != null) this.coord.y = val; return this.coord.y; } sqsize() { return this.x() ** 2 + this.y() ** 2; } size() { return Math.sqrt(this.sqsize()); } add(other: Vec) { return new Vec({ x: this.x() + other.x(), y: this.y() + other.y(), }); } sub(other: Vec) { return new Vec({ x: this.x() - other.x(), y: this.y() - other.y(), }); } mul(other: Vec | number) { if (other instanceof Vec) return new Vec({ x: this.x() * other.x(), y: this.y() * other.y(), }); return new Vec({ x: this.x() * other, y: this.y() * other, }); } div(other: Vec | number) { if (other instanceof Vec) return new Vec({ x: this.x() / other.x(), y: this.y() / other.y(), }); return new Vec({ x: this.x() / other, y: this.y() / other, }); } dot(other: Vec): number { return this.x() * other.x() + this.y() * other.y(); } unit() { return this.div(this.size()); } xy(): XY { return { x: this.x(), y: this.y(), }; } } export function xy(x: number, y: number): XY { // lazy shorthand return { x: x, y: y }; } export function xyvec(x: number, y: number): Vec { // even lazier shorthand! :D... yaaawn... return new Vec(xy(x, y)); } export function rgb(r: number, g: number, b: number): Color { // .....zzzzz.... return { r: r, g: g, b: b }; } export function intersect(...boundaries: Bounds[]): Bounds { let res = { left: -Infinity, top: -Infinity, right: Infinity, bottom: Infinity }; boundaries.forEach((b) => { if (b.left > res.left) res.left = b.left; if (b.top > res.top) res.top = b.top; if (b.right < res.right) res.right = b.right; if (b.bottom < res.bottom) res.bottom = b.bottom; }); return res; } export function union(...boundaries: Bounds[]): Bounds { let res = { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity }; boundaries.forEach((b) => { if (b.left < res.left) res.left = b.left; if (b.top < res.top) res.top = b.top; if (b.right > res.right) res.right = b.right; if (b.bottom > res.bottom) res.bottom = b.bottom; }); return res; } export function sizeBounds(size: XY, offs: XY = xy(0, 0)): Bounds { return { left: offs.x, top: offs.y, right: size.x + offs.x, bottom: size.y + offs.y, }; } export function boundsPos(bounds: Bounds): XY { return { x: bounds.left, y: bounds.top }; } export function boundsSize(bounds: Bounds): XY { return { x: bounds.right - bounds.left, y: bounds.bottom - bounds.top }; } export function moveBounds(bounds: Bounds, offs: XY): Bounds { return { left: bounds.left + offs.x, top: bounds.top + offs.y, right: bounds.right + offs.x, bottom: bounds.bottom + offs.y, }; } export function ltrb(l: number, t: number, r: number, b: number): Bounds { return { left: l, top: t, right: r, bottom: b } } export function printBounds(bo: Bounds) { let t = '' + bo.top; let l = '' + bo.left; let r = '' + bo.right; let b = '' + bo.bottom; console.log(`${' '.repeat(l.length)} ${t}\n${' '.repeat(l.length)} +${'-'.repeat(Math.max(t.length - 2, 1))}+\n${l} |${' '.repeat(Math.max(t.length - 2, 1))}| ${r}\n${' '.repeat(l.length)} +${'-'.repeat(Math.max(t.length - 2, 1))}+\n${' '.repeat(l.length)} ${b}`); }