Skip to content

Commit

Permalink
update types
Browse files Browse the repository at this point in the history
  • Loading branch information
OrionReed committed Dec 2, 2024
1 parent b1e20bf commit 7969bdb
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 92 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build --base=/folk-canvas",
"preview": "vite build && vite preview"
"build": "tsc --noEmit && vite build --base=/folk-canvas",
"preview": "tsc --noEmit && vite build && vite preview",
"types": "tsc --noEmit"
},
"dependencies": {
"@babel/parser": "^7.26.2",
Expand Down
107 changes: 107 additions & 0 deletions src/common/Vector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import type { Point } from './types.ts';

export class Vector {
/**
* Creates a zero vector (0,0)
* @returns {Point} A point representing a zero vector
*/
static zero(): Point {
return { x: 0, y: 0 };
}

/**
* Subtracts vector b from vector a
* @param {Point} a - The first vector
* @param {Point} b - The vector to subtract
* @returns {Point} The resulting vector
*/
static sub(a: Point, b: Point): Point {
return { x: a.x - b.x, y: a.y - b.y };
}

/**
* Adds two vectors together
* @param {Point} a - The first vector
* @param {Point} b - The second vector
* @returns {Point} The sum of the two vectors
*/
static add(a: Point, b: Point): Point {
return { x: a.x + b.x, y: a.y + b.y };
}

/**
* Multiplies two vectors component-wise
* @param {Point} a - The first vector
* @param {Point} b - The second vector
* @returns {Point} The component-wise product of the two vectors
*/
static mult(a: Point, b: Point): Point {
return { x: a.x * b.x, y: a.y * b.y };
}

/**
* Scales a vector by a scalar value
* @param {Point} v - The vector to scale
* @param {number} scaleFactor - The scaling factor
* @returns {Point} The scaled vector
*/
static scale(v: Point, scaleFactor: number): Point {
return { x: v.x * scaleFactor, y: v.y * scaleFactor };
}

/**
* Calculates the magnitude (length) of a vector
* @param {Point} v - The vector
* @returns {number} The magnitude of the vector
*/
static mag(v: Point): number {
return Math.hypot(v.x, v.y);
}

/**
* Returns a normalized (unit) vector in the same direction
* @param {Point} v - The vector to normalize
* @returns {Point} The normalized vector
*/
static normalized(v: Point): Point {
const magnitude = Vector.mag(v);
return magnitude === 0 ? Vector.zero() : { x: v.x / magnitude, y: v.y / magnitude };
}

/**
* Calculates the Euclidean distance between two points
* @param {Point} a - The first point
* @param {Point} b - The second point
* @returns {number} The distance between the points
*/
static distance(a: Point, b: Point): number {
return Math.hypot(a.x - b.x, a.y - b.y);
}

/**
* Calculates the squared distance between two points
* Useful for performance when comparing distances
* @param {Point} a - The first point
* @param {Point} b - The second point
* @returns {number} The squared distance between the points
*/
static distanceSquared(a: Point, b: Point): number {
const dx = a.x - b.x;
const dy = a.y - b.y;
return dx * dx + dy * dy;
}

/**
* Linearly interpolates between two points
* @param {Point} a - The starting point
* @param {Point} b - The ending point
* @param {number} t - The interpolation parameter (0-1)
* @returns {Point} The interpolated point
*/
static lerp(a: Point, b: Point, t: number): Point {
return {
x: a.x + (b.x - a.x) * t,
y: a.y + (b.y - a.y) * t,
};
}
}
17 changes: 0 additions & 17 deletions src/common/Vector2.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Point = { x: number; y: number };
42 changes: 14 additions & 28 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
// Adopted from: https://github.com/pshihn/bezier-points/blob/master/src/index.ts

export type Point = [number, number];

export interface Vertex {
x: number;
y: number;
}

// distance between 2 points
function distance(p1: Point, p2: Point): number {
return Math.sqrt(distanceSq(p1, p2));
}

// distance between 2 points squared
function distanceSq(p1: Point, p2: Point): number {
return Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2);
}
import type { Point } from './types.ts';
import { Vector } from './Vector.ts';

// Distance squared from a point p to the line segment vw
function distanceToSegmentSq(p: Point, v: Point, w: Point): number {
const l2 = distanceSq(v, w);
const l2 = Vector.distanceSquared(v, w);
if (l2 === 0) {
return distanceSq(p, v);
return Vector.distanceSquared(p, v);
}
let t = ((p[0] - v[0]) * (w[0] - v[0]) + (p[1] - v[1]) * (w[1] - v[1])) / l2;
let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
t = Math.max(0, Math.min(1, t));
return distanceSq(p, lerp(v, w, t));
return Vector.distanceSquared(p, Vector.lerp(v, w, t));
}

function lerp(a: Point, b: Point, t: number): Point {
return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
}

// Adapted from https://seant23.wordpress.com/2010/11/12/offset-bezier-curves/
Expand All @@ -39,13 +25,13 @@ function flatness(points: readonly Point[], offset: number): number {
const p3 = points[offset + 2];
const p4 = points[offset + 3];

let ux = 3 * p2[0] - 2 * p1[0] - p4[0];
let ux = 3 * p2.x - 2 * p1.x - p4.x;
ux *= ux;
let uy = 3 * p2[1] - 2 * p1[1] - p4[1];
let uy = 3 * p2.y - 2 * p1.y - p4.y;
uy *= uy;
let vx = 3 * p3[0] - 2 * p4[0] - p1[0];
let vx = 3 * p3.x - 2 * p4.x - p1.x;
vx *= vx;
let vy = 3 * p3[1] - 2 * p4[1] - p1[1];
let vy = 3 * p3.y - 2 * p4.y - p1.y;
vy *= vy;

if (ux < vx) {
Expand All @@ -69,7 +55,7 @@ function getPointsOnBezierCurveWithSplitting(
if (flatness(points, offset) < tolerance) {
const p0 = points[offset + 0];
if (outPoints.length) {
const d = distance(outPoints[outPoints.length - 1], p0);
const d = Vector.distance(outPoints[outPoints.length - 1], p0);
if (d > 1) {
outPoints.push(p0);
}
Expand Down Expand Up @@ -176,15 +162,15 @@ export function getSvgPathFromStroke(stroke: number[][]): string {
return d.join(' ');
}

export function verticesToPolygon(vertices: Vertex[]): string {
export function verticesToPolygon(vertices: Point[]): string {
if (vertices.length === 0) return '';

return `polygon(${vertices.map((vertex) => `${vertex.x}px ${vertex.y}px`).join(', ')})`;
}

const vertexRegex = /(?<x>-?([0-9]*[.])?[0-9]+),\s*(?<y>-?([0-9]*[.])?[0-9]+)/;

export function parseVertex(str: string): Vertex | null {
export function parseVertex(str: string): Point | null {
const results = vertexRegex.exec(str);

if (results === null) return null;
Expand Down
8 changes: 4 additions & 4 deletions src/folk-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ export class FolkConnection extends AbstractArrow {
) as Arrow;

const points = pointsOnBezierCurves([
[sx, sy],
[cx, cy],
[ex, ey],
[ex, ey],
{ x: sx, y: sy },
{ x: cx, y: cy },
{ x: ex, y: ey },
{ x: ex, y: ey },
]);

const stroke = getStroke(points, this.#options);
Expand Down
30 changes: 15 additions & 15 deletions src/folk-hull.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FolkSet } from './folk-set';
import { Vertex, verticesToPolygon } from './common/utils';

import { verticesToPolygon } from './common/utils';
import type { Point } from './common/types';
declare global {
interface HTMLElementTagNameMap {
'folk-hull': FolkHull;
Expand All @@ -10,9 +10,9 @@ declare global {
export class FolkHull extends FolkSet {
static tagName = 'folk-hull';

#hull: Vertex[] = [];
#hull: Point[] = [];

get hull(): ReadonlyArray<Vertex> {
get hull(): ReadonlyArray<Point> {
return this.#hull;
}

Expand Down Expand Up @@ -50,16 +50,16 @@ export class FolkHull extends FolkSet {
* If not, see <http://www.gnu.org/licenses/>.
*/

function comparePoints(a: Vertex, b: Vertex): number {
function comparePoints(a: Point, b: Point): number {
if (a.x < b.x) return -1;
if (a.x > b.x) return 1;
if (a.y < b.y) return -1;
if (a.y > b.y) return 1;
return 0;
}

export function makeHull(rects: DOMRectReadOnly[]): Vertex[] {
const points: Vertex[] = rects
export function makeHull(rects: DOMRectReadOnly[]): Point[] {
const points: Point[] = rects
.flatMap((rect) => [
{ x: rect.left, y: rect.top },
{ x: rect.right, y: rect.top },
Expand All @@ -74,25 +74,25 @@ export function makeHull(rects: DOMRectReadOnly[]): Vertex[] {
// as per the mathematical convention, instead of "down" as per the computer
// graphics convention. This doesn't affect the correctness of the result.

const upperHull: Array<Vertex> = [];
const upperHull: Array<Point> = [];
for (let i = 0; i < points.length; i++) {
const p: Vertex = points[i];
const p: Point = points[i];
while (upperHull.length >= 2) {
const q: Vertex = upperHull[upperHull.length - 1];
const r: Vertex = upperHull[upperHull.length - 2];
const q: Point = upperHull[upperHull.length - 1];
const r: Point = upperHull[upperHull.length - 2];
if ((q.x - r.x) * (p.y - r.y) >= (q.y - r.y) * (p.x - r.x)) upperHull.pop();
else break;
}
upperHull.push(p);
}
upperHull.pop();

const lowerHull: Array<Vertex> = [];
const lowerHull: Array<Point> = [];
for (let i = points.length - 1; i >= 0; i--) {
const p: Vertex = points[i];
const p: Point = points[i];
while (lowerHull.length >= 2) {
const q: Vertex = lowerHull[lowerHull.length - 1];
const r: Vertex = lowerHull[lowerHull.length - 2];
const q: Point = lowerHull[lowerHull.length - 1];
const r: Point = lowerHull[lowerHull.length - 2];
if ((q.x - r.x) * (p.y - r.y) >= (q.y - r.y) * (p.x - r.x)) lowerHull.pop();
else break;
}
Expand Down
6 changes: 4 additions & 2 deletions src/folk-llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ export class FolkLLM extends HTMLElement {
this.#update(new Set(['systemPrompt', 'prompt']));
}

#session;
#session: any;

#isModelReady = window?.ai.languageModel.capabilities().then((capabilities) => capabilities.available === 'readily');
#isModelReady = window?.ai.languageModel
.capabilities()
.then((capabilities: any) => capabilities.available === 'readily');

#systemPrompt: Prompt = this.getAttribute('system-prompt') || '';
get systemPrompt() {
Expand Down
14 changes: 7 additions & 7 deletions src/folk-rope.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// This is a rewrite of https://github.com/guerrillacontra/html5-es6-physics-rope

import { Vector, type Vector2 } from './common/Vector2.ts';
import { Vector } from './common/Vector.ts';
import type { Point } from './common/types.ts';
import { AbstractArrow } from './abstract-arrow.ts';
import { Vertex } from './common/utils.ts';

const lerp = (first: number, second: number, percentage: number) => first + (second - first) * percentage;

// Each rope part is one of these uses a high precision variant of Störmer–Verlet integration to keep the simulation consistent otherwise it would "explode"!
interface RopePoint {
pos: Vertex;
pos: Point;
distanceToNextPoint: number;
isFixed: boolean;
oldPos: Vertex;
velocity: Vertex;
oldPos: Point;
velocity: Point;
mass: number;
damping: number;
prev: RopePoint | null;
Expand Down Expand Up @@ -162,7 +162,7 @@ export class FolkRope extends AbstractArrow {
}
}

#generatePoints(start: Vertex, end: Vertex) {
#generatePoints(start: Point, end: Point) {
const delta = Vector.sub(end, start);
const len = Vector.mag(delta);
const resolution = 5;
Expand Down Expand Up @@ -202,7 +202,7 @@ export class FolkRope extends AbstractArrow {
return points;
}

#integratePoint(point: RopePoint, gravity: Vector2) {
#integratePoint(point: RopePoint, gravity: Point) {
if (!point.isFixed) {
point.velocity = Vector.sub(point.pos, point.oldPos);
point.oldPos = { ...point.pos };
Expand Down
Loading

0 comments on commit 7969bdb

Please sign in to comment.