我打算在距给定坐标最近的线上找到坐标。 假设我有一行。
var line={x0:114,y0:366,x1:306,y1:30};
我有一些随机坐标,例如300和200都以像素为单位。 我可以将直线与直线概念连接起来。 从给定坐标开始的最短坐标的功能是:
function getClosestPointOnLine(line,x,y) {
lerp=function(a,b,x){ return(a+x*(b-a)); };
var dx=line.x1-line.x0;
var dy=line.y1-line.y0;
var t=((x-line.x0)*dx+(y-line.y0)*dy)/(dx*dx+dy*dy);
t=Math.min(1,Math.max(0,t));
var lineX=lerp(line.x0, line.x1, t);
var lineY=lerp(line.y0, line.y1, t);
return({x:lineX,y:lineY});
};
然后将线路与:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cord=getClosestPointOnLine(line_d,x,y);
ctx.lineTo(cord3.x,cord3.y);
示例为:
我应该如何改变方法以获得理想的结果。
答案 0 :(得分:2)
您在一条线上有一个点,并且有一个角度,因此可以使用一些trigo轻松绘制线:
const pt1 = {
x: 120,
y: 100
};
const r = 30; // length of our segment, not really needed afterward
const ctx = canvas.getContext('2d');
function draw() {
const angle = inp.value;
// find pt2 using trigonometry
const pt2 = {
x: pt1.x + r * Math.cos(angle),
y: pt1.y + r * Math.sin(angle)
};
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(pt1.x - 2, pt1.y - 2, 4, 4);
ctx.fillRect(pt2.x - 2, pt2.y - 2, 4, 4);
ctx.beginPath();
ctx.moveTo(pt1.x, pt1.y);
ctx.lineTo(pt2.x, pt2.y);
ctx.stroke();
}
inp.oninput = draw;
draw();
<input type="range" id="inp" min="0" max="6.29" step="0.01"><br>
<canvas id="canvas"></canvas>
所以现在,您需要找到的是这两条线的交点:
const line1 = {
x1: 30,
y1: 30,
x2: 10,
y2: 100
};
const pt1 = {
x: 80,
y: 80
}
const ctx = canvas.getContext('2d');
function draw(x, y) {
angle = inp.value;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'gray';
ctx.beginPath();
ctx.moveTo(line1.x1, line1.y1);
ctx.lineTo(line1.x2, line1.y2);
ctx.stroke();
const line2 = {
x1: pt1.x,
y1: pt1.y,
// here our radius can be hardcoded
x2: pt1.x + 1 * Math.cos(angle),
y2: pt1.y + 1 * Math.sin(angle)
}
const inter = intersect(
line1.x1, line1.y1, line1.x2, line1.y2,
line2.x1, line2.y1, line2.x2, line2.y2
);
if (!inter) {
ctx.fillText('parrallel', 20, 20);
return;
}
if (inter.x < Math.min(line1.x1, line1.x2) || inter.x > Math.max(line1.x1, line1.x2) ||
inter.y < Math.min(line1.y1, line1.y2) || inter.y > Math.max(line1.y1, line1.y2)) {
ctx.fillText('Out of bounds', 20, 20);
return;
}
ctx.strokeStyle = 'green';
ctx.beginPath();
ctx.moveTo(pt1.x, pt1.y);
ctx.lineTo(inter.x, inter.y);
ctx.stroke();
}
document.onmousemove = e => {
const rect = canvas.getBoundingClientRect();
pt1.x = e.clientX - rect.left;
pt1.y = e.clientY - rect.top;
draw();
};
inp.oninput = draw;
draw();
/* Edited from http://paulbourke.net/geometry/pointlineplane/javascript.txt */
function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
// Check if none of the lines are of length 0
if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) {
return false
}
denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
// Lines are parallel
if (denominator === 0) {
return false
}
let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator
let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator
// Return a object with the x and y coordinates of the intersection
let x = x1 + ua * (x2 - x1)
let y = y1 + ua * (y2 - y1)
return {
x,
y
}
}
<input type="range" id="inp" min="0" max="6.29" step="0.01" value="0"><br>
<canvas id="canvas"></canvas>
并且您会注意到在这种情况下没有“ 最接近”点,因为您始终最多只有一个满足这些条件的点。