UNPKG

@mathigon/euclid

Version:

Euclidean geometry classes and tools for JavaScript

66 lines (52 loc) 1.87 kB
// ============================================================================= // Euclid.js | Utilities // (c) Mathigon // ============================================================================= import {mod} from '@mathigon/fermat'; import {Line} from './line'; import {Point} from './point'; export type TransformMatrix = [[number, number, number], [number, number, number]]; export type SimplePoint = {x: number, y: number}; export interface GeoElement { type: string; transform(matrix: TransformMatrix): GeoElement; rotate(angle: number, center?: SimplePoint): GeoElement; reflect(l: Line): GeoElement; scale(sx: number, sy?: number): GeoElement; shift(x: number, y?: number): GeoElement; translate(p: Point): GeoElement; equals(other: GeoElement, tolerance?: number, oriented?: boolean): boolean; toString(): string; } export interface GeoShape extends GeoElement { project(p: Point): Point; contains(p: Point, tolerance?: number): boolean; at(t: number): Point; offset(p: Point): number; rotate(angle: number, center?: SimplePoint): GeoShape; reflect(l: Line): GeoShape; scale(sx: number, sy?: number): GeoShape; shift(x: number, y?: number): GeoShape; translate(p: SimplePoint): GeoShape; } export const TWO_PI = 2 * Math.PI; export function rad(p: SimplePoint, c?: SimplePoint) { const a = Math.atan2(p.y - (c ? c.y : 0), p.x - (c ? c.x : 0)); return mod(a, TWO_PI); } // TODO Merge this with findMin() in @mathigon/core export function findClosest(p: Point, items: GeoShape[]): [Point, number]|undefined { let q: Point|undefined = undefined; let d = Infinity; let index = -1; for (const [i, e] of items.entries()) { const q1 = e.project(p); const d1 = Point.distance(p, q1); if (d1 < d) { q = q1; d = d1; index = i; } } return q ? [q, index] : undefined; }