Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Created November 4, 2019 13:01
Show Gist options
  • Save steveruizok/b9e2fccdc93e24f2cb06c1751a2e95b0 to your computer and use it in GitHub Desktop.
Save steveruizok/b9e2fccdc93e24f2cb06c1751a2e95b0 to your computer and use it in GitHub Desktop.
Returns whether or not a point lies within a polygon (an array of vertices).
// Hit testing algorithm
const ccw = (A: [number, number], B: [number, number], C: [number, number]) =>
(C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0])
export const intersect = (
A: [number, number],
B: [number, number],
C: [number, number],
D: [number, number]
) => ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D)
/**
* Get whether or not a given point lies within a polygon.
* @param point A point (x and y).
* @param vertices: An array of points.
* @param minX (optional) The minimum x value to check against.
*/
export function pointInPolygon(
point: { x: number; y: number },
vertices: { x: number; y: number }[],
minX?: number
): boolean
export function pointInPolygon(
point: [number, number],
vertices: [number, number][],
minX?: number
): boolean
export function pointInPolygon(point: any, vertices: any[], minX = -999) {
let ps = !!(point as { x: number; y: number }).x
? [
(point as { x: number; y: number }).x,
(point as { x: number; y: number }).y,
]
: point
let ts: [number, number][] = !!(vertices[0] as { x: number; y: number }).x
? (vertices as { x: number; y: number }[]).map((p) => [p.x, p.y])
: (vertices as [number, number][])
let inside = false
let i = 0
let j = ts.length - 1
while (i < ts.length) {
if (intersect([minX, ps[1]], [ps[0], ps[1]], ts[i], ts[j])) {
inside = !inside
}
j = i++
}
return inside
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment