Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Last active March 23, 2021 06:08
Show Gist options
  • Save steveruizok/3b80882ada0b10539bc88a41042faf4d to your computer and use it in GitHub Desktop.
Save steveruizok/3b80882ada0b10539bc88a41042faf4d to your computer and use it in GitHub Desktop.
Get the minimum distance between a point and a line. Get the nearest point on a line to a second point.
/**
* Get the minimum distance from a point P to a line with a segment AB.
* @param A The start of the line.
* @param B The end of the line.
* @param P A point.
* @returns
*/
export function distanceToLine(A: number[], B: number[], P: number[]) {
const delta = sub(B, A)
const angle = Math.atan2(delta[1], delta[0])
const dir = rot(sub(P, A), -angle)
return dir[1]
}
/**
* Get the nearest point on a line segment AB.
* @param A The start of the line.
* @param B The end of the line.
* @param P A point.
* @param clamp Whether to clamp the resulting point to the segment.
* @returns
*/
export function nearestPointOnLine(
A: number[],
B: number[],
P: number[],
clamp = true
) {
const delta = sub(B, A)
const angle = Math.atan2(delta[1], delta[0])
const length = len(delta)
const dir = rot(sub(P, A), -angle)
if (clamp) {
if (dir[0] < 0) return A
if (dir[0] > length) return B
}
return add(A, div(mul(delta, dir[0]), length))
}
// Vector utilities
export function add(A: number[], B: number[]) {
return [A[0] + B[0], A[1] + B[1]]
}
export function sub(A: number[], B: number[]) {
return [A[0] - B[0], A[1] - B[1]]
}
export function div(A: number[], n: number) {
return [A[0] / n, A[1] / n]
}
export function mul(A: number[], n: number) {
return [A[0] * n, A[1] * n]
}
export function dpr(A: number[], B: number[]) {
return A[0] * B[0] + A[1] * B[1]
}
export function cpr(A: number[], B: number[]) {
return A[0] * B[1] - B[0] * A[1]
}
export function len(A: number[]) {
return Math.hypot(A[0], A[1])
}
export function rot(A: number[], r: number) {
return [
A[0] * Math.cos(r) - A[1] * Math.sin(r),
A[1] * Math.cos(r) + A[0] * Math.sin(r),
]
}
// Thanks to https://observablehq.com/@tomktjemsland/distance-from-point-to-line
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment