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]); }