import concaveman from 'concaveman' export class Intersections { public static circleCircle(circle1: {x: number, y: number, r: number}, circle2: {x: number, y: number, r: number}) { const dx = circle1.x - circle2.x const dy = circle1.y - circle2.y const distance = Math.sqrt(dx * dx + dy * dy) return distance < (circle1.r + circle2.r) } } export default class Geometry { public static concaveHull (points: [number, number][], concavity?: number, lengthThreshold?: number): [number, number][] { if (points.length < 3) return points const hull = concaveman(points, concavity, lengthThreshold) as [number, number][] return hull } public static convexHull (points: [number, number][]): [number, number][] { if (points.length < 3) return points // Sort points by x, then by y const sorted = points.slice().sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])) const crossProduct = (o: [number, number], a: [number, number], b: [number, number]) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]) const buildHull = (pts: [number, number][]) => { const hull: [number, number][] = [] for (const p of pts) { while (hull.length >= 2 && crossProduct(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) { hull.pop() } hull.push(p) } return hull } const lowerHull = buildHull(sorted) const upperHull = buildHull(sorted.reverse()) // Remove last point from each hull to avoid duplication lowerHull.pop() upperHull.pop() return lowerHull.concat(upperHull) } public static Intersections = Intersections }