Last active
September 4, 2018 09:01
-
-
Save phuwin1995/8093a970aeee36f9be1bf5949357b7bc to your computer and use it in GitHub Desktop.
Get a project point to a closest line in an array of lines
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://jsfiddle.net/soulwire/UA6H5/ | |
function projectPointToLine(x, y, x1, y1, x2, y2) { | |
const p = { | |
x: x, | |
y: y | |
}, | |
a = { | |
x: x1, | |
y: y1 | |
}, | |
b = { | |
x: x2, | |
y: y2 | |
}; | |
const atob = { | |
x: b.x - a.x, | |
y: b.y - a.y | |
}; | |
const atop = { | |
x: p.x - a.x, | |
y: p.y - a.y | |
}; | |
const len = atob.x * atob.x + atob.y * atob.y; | |
let dot = atop.x * atob.x + atop.y * atob.y; | |
const t = Math.min(1, Math.max(0, dot / len)); | |
dot = (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x); | |
return { | |
point: { | |
x: a.x + atob.x * t, | |
y: a.y + atob.y * t | |
}, | |
left: dot < 1, | |
dot: dot, | |
t: t | |
}; | |
} | |
// https://stackoverflow.com/a/6853926/3588080 | |
function pointToLineDistance(x, y, x1, y1, x2, y2) { | |
const A = x - x1; | |
const B = y - y1; | |
const C = x2 - x1; | |
const D = y2 - y1; | |
const dot = A * C + B * D; | |
const len_sq = C * C + D * D; | |
let param = -1; | |
if (len_sq != 0) | |
param = dot / len_sq; | |
let xx, yy; | |
if (param < 0) { | |
xx = x1; | |
yy = y1; | |
} else if (param > 1) { | |
xx = x2; | |
yy = y2; | |
} else { | |
xx = x1 + param * C; | |
yy = y1 + param * D; | |
} | |
const dx = x - xx; | |
const dy = y - yy; | |
return Math.sqrt(dx * dx + dy * dy); | |
} | |
function getClosestPointToALine(x, y, fixedLines) { | |
const closestLine = getClosestLineToAPoint(x, y, fixedLines); | |
return projectPointToLine(x, y, closestLine.x1, closestLine.y1, closestLine.x2, closestLine.y2).point; | |
} | |
function getClosestLineToAPoint(x, y, fixedLines) { | |
let closestLine, smallestDistance = -999; | |
fixedLines.forEach(function(line) { | |
if (!closestLine) { | |
closestLine = line; | |
smallestDistance = pointToLineDistance(x, y, line.x1, line.y1, line.x2, line.y2); | |
} else { | |
var distance = pointToLineDistance(x, y, line.x1, line.y1, line.x2, line.y2); | |
if (distance < smallestDistance) { | |
closestLine = line; | |
smallestDistance = distance; | |
} | |
} | |
}) | |
return closestLine; | |
} | |
class Line { | |
constructor(x1, y1, x2, y2) { | |
this.x1 = x1; | |
this.y1 = y1; | |
this.x2 = x2; | |
this.y2 = y2; | |
} | |
} | |
const fixedLines = [ | |
new Line(0, 2, 2, 0), | |
new Line(0, 0, 0, 2), | |
new Line(0, 0, 2, 0) | |
] | |
console.log(getClosestPointToALine(0,0,fixedLines)) // {x: 0, y: 0} | |
console.log(getClosestPointToALine(0,2,fixedLines)) // {x: 0, y: 2} | |
console.log(getClosestPointToALine(2,0,fixedLines)) // {x: 2, y: 0} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment