(points: Point[])
| 121 | |
| 122 | // Computes the convex hull of a set of points using the monotone chain algorithm. |
| 123 | function convexHull(points: Point[]): Point[] { |
| 124 | let sorted = points.slice().sort((a, b) => a.x - b.x || a.y - b.y); |
| 125 | if (sorted.length < 3) { |
| 126 | return sorted; |
| 127 | } |
| 128 | |
| 129 | let cross = (o: Point, a: Point, b: Point) => |
| 130 | (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); |
| 131 | |
| 132 | let lower: Point[] = []; |
| 133 | for (let p of sorted) { |
| 134 | while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) { |
| 135 | lower.pop(); |
| 136 | } |
| 137 | lower.push(p); |
| 138 | } |
| 139 | |
| 140 | let upper: Point[] = []; |
| 141 | for (let i = sorted.length - 1; i >= 0; i--) { |
| 142 | let p = sorted[i]; |
| 143 | while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) { |
| 144 | upper.pop(); |
| 145 | } |
| 146 | upper.push(p); |
| 147 | } |
| 148 | |
| 149 | lower.pop(); |
| 150 | upper.pop(); |
| 151 | return lower.concat(upper); |
| 152 | } |
| 153 | |
| 154 | // Ray casting point-in-polygon test. |
| 155 | function isPointInPolygon(point: Point, polygon: Point[]): boolean { |
no test coverage detected