From c7a3580f9fbaef5a425840383121e47486c30264 Mon Sep 17 00:00:00 2001 From: Orion Reed Date: Mon, 2 Dec 2024 18:07:01 -0500 Subject: [PATCH] add rotation utils --- src/common/Vector.ts | 31 +++++++++++++++++++++++++++++++ src/folk-shape.ts | 33 ++++++++++++--------------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/common/Vector.ts b/src/common/Vector.ts index de8a691..58fb056 100644 --- a/src/common/Vector.ts +++ b/src/common/Vector.ts @@ -104,4 +104,35 @@ export class Vector { y: a.y + (b.y - a.y) * t, }; } + + /** + * Rotates a vector by a given angle (in radians) + * @param {Point} v - The vector to rotate + * @param {number} angle - The angle in radians + * @returns {Point} The rotated vector + */ + static rotate(v: Point, angle: number): Point { + const cos = Math.cos(angle); + const sin = Math.sin(angle); + return { + x: v.x * cos - v.y * sin, + y: v.x * sin + v.y * cos, + }; + } + + /** + * Rotates a point around a pivot point by a given angle (in radians) + * @param {Point} point - The point to rotate + * @param {Point} pivot - The point to rotate around + * @param {number} angle - The angle in radians + * @returns {Point} The rotated point + */ + static rotateAround(point: Point, pivot: Point, angle: number): Point { + // Translate to origin + const translated = Vector.sub(point, pivot); + // Rotate around origin + const rotated = Vector.rotate(translated, angle); + // Translate back + return Vector.add(rotated, pivot); + } } diff --git a/src/folk-shape.ts b/src/folk-shape.ts index 69b078d..41463e7 100644 --- a/src/folk-shape.ts +++ b/src/folk-shape.ts @@ -1,22 +1,23 @@ import { css, html } from './common/tags'; import { ResizeObserverManager } from './common/resize-observer'; import type { Point } from './common/types'; +import { Vector } from './common/Vector'; const resizeObserver = new ResizeObserverManager(); export type Shape = 'rectangle' | 'circle' | 'triangle'; type RotatedDOMRect = DOMRect & { - // In degrees + /** in degrees */ rotation: number; - // Returns the center point in worldspace coordinates + /** Returns the center point in worldspace coordinates */ center(): Point; - // Returns the four corners in worldspace coordinates, in clockwise order + /** Returns the four corners in worldspace coordinates, in clockwise order */ corners(): [Point, Point, Point, Point]; - // Returns all the vertices in worldspace coordinates + /** Returns all the vertices in worldspace coordinates */ vertices(): Point[]; }; export type MoveEventDetail = { movementX: number; movementY: number }; @@ -322,26 +323,16 @@ export class FolkShape extends HTMLElement { return []; }, - corners(): [Point, Point, Point, Point] { + corners() { const center = this.center(); - const cos = Math.cos(radians); - const sin = Math.sin(radians); + const radians = (this.rotation * Math.PI) / 180; + const { x, y, width, height } = this; - const halfWidth = this.width / 2; - const halfHeight = this.height / 2; - - // Helper to rotate a point around the center - const rotatePoint = (dx: number, dy: number): Point => ({ - x: center.x + dx * cos - dy * sin, - y: center.y + dx * sin + dy * cos, - }); - - // Return vertices in clockwise order: top-left, top-right, bottom-right, bottom-left return [ - rotatePoint(-halfWidth, -halfHeight), // Top-left - rotatePoint(halfWidth, -halfHeight), // Top-right - rotatePoint(halfWidth, halfHeight), // Bottom-right - rotatePoint(-halfWidth, halfHeight), // Bottom-left + Vector.rotateAround({ x, y }, center, radians), + Vector.rotateAround({ x: x + width, y }, center, radians), + Vector.rotateAround({ x: x + width, y: y + height }, center, radians), + Vector.rotateAround({ x, y: y + height }, center, radians), ]; },