Skip to content

Instantly share code, notes, and snippets.

@phuwin1995
Last active September 4, 2018 09:01
Show Gist options
  • Save phuwin1995/8093a970aeee36f9be1bf5949357b7bc to your computer and use it in GitHub Desktop.
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
// 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