From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Sun, 15 Mar 2026 16:19:35 -0400 Subject: refactor: packages/ --- packages/math/polygon.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/math/polygon.ts (limited to 'packages/math/polygon.ts') diff --git a/packages/math/polygon.ts b/packages/math/polygon.ts new file mode 100644 index 0000000..783bc4c --- /dev/null +++ b/packages/math/polygon.ts @@ -0,0 +1,72 @@ +import { pointsEqual } from "./point"; +import { lineSegment, pointOnLineSegment } from "./segment"; +import type { GlobalPoint, LocalPoint, Polygon } from "./types"; +import { PRECISION } from "./utils"; + +export function polygon( + ...points: Point[] +) { + return polygonClose(points) as Polygon; +} + +export function polygonFromPoints( + points: Point[], +) { + return polygonClose(points) as Polygon; +} + +export const polygonIncludesPoint = ( + point: Point, + polygon: Polygon, +) => { + const x = point[0]; + const y = point[1]; + let inside = false; + + for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + const xi = polygon[i][0]; + const yi = polygon[i][1]; + const xj = polygon[j][0]; + const yj = polygon[j][1]; + + if ( + ((yi > y && yj <= y) || (yi <= y && yj > y)) && + x < ((xj - xi) * (y - yi)) / (yj - yi) + xi + ) { + inside = !inside; + } + } + + return inside; +}; + +export const pointOnPolygon = ( + p: Point, + poly: Polygon, + threshold = PRECISION, +) => { + let on = false; + + for (let i = 0, l = poly.length - 1; i < l; i++) { + if (pointOnLineSegment(p, lineSegment(poly[i], poly[i + 1]), threshold)) { + on = true; + break; + } + } + + return on; +}; + +function polygonClose( + polygon: Point[], +) { + return polygonIsClosed(polygon) + ? polygon + : ([...polygon, polygon[0]] as Polygon); +} + +function polygonIsClosed( + polygon: Point[], +) { + return pointsEqual(polygon[0], polygon[polygon.length - 1]); +} -- cgit v1.2.3