readme
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import type { Point } from '../types';
|
||||
|
||||
export function pointInPolygon(p: Point, poly: Point[]): boolean {
|
||||
if (poly.length < 3) return true;
|
||||
let inside = false;
|
||||
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
|
||||
const a = poly[i];
|
||||
const b = poly[j];
|
||||
if (onSegment(a, b, p)) return true;
|
||||
const intersect = a.y > p.y !== b.y > p.y && p.x < ((b.x - a.x) * (p.y - a.y)) / (b.y - a.y) + a.x;
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
function onSegment(a: Point, b: Point, p: Point): boolean {
|
||||
const cross = (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);
|
||||
if (Math.abs(cross) > 1e-9) return false;
|
||||
const dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
|
||||
if (dot < 0) return false;
|
||||
const len2 = (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
|
||||
return dot <= len2;
|
||||
}
|
||||
|
||||
function closestOnSegment(a: Point, b: Point, p: Point): Point {
|
||||
const dx = b.x - a.x;
|
||||
const dy = b.y - a.y;
|
||||
const len2 = dx * dx + dy * dy;
|
||||
if (len2 === 0) return { ...a };
|
||||
let t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2;
|
||||
t = Math.max(0, Math.min(1, t));
|
||||
return { x: a.x + t * dx, y: a.y + t * dy };
|
||||
}
|
||||
|
||||
export function nearestPointInPolygon(p: Point, poly: Point[]): Point {
|
||||
if (poly.length < 3) return { ...p };
|
||||
if (pointInPolygon(p, poly)) return { ...p };
|
||||
let best = poly[0];
|
||||
let bestD = Infinity;
|
||||
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
|
||||
const q = closestOnSegment(poly[j], poly[i], p);
|
||||
const d = (q.x - p.x) ** 2 + (q.y - p.y) ** 2;
|
||||
if (d < bestD) {
|
||||
bestD = d;
|
||||
best = q;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
export function rectanglePoints(width: number, height: number): Point[] {
|
||||
return [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: width, y: 0 },
|
||||
{ x: width, y: height },
|
||||
{ x: 0, y: height },
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user