找到一条直线的垂直点
Find a point on perpendicular of a line
我有一个角度为 A 的不规则多边形 (x1,y1) (x2,y2) 的边和边的中点 (mx, my)。
我需要在 A 穿过 (mx, my) 的垂线上找到两个点 (x3,y3) 和 (x4,y4),并有一些偏移。这样我就可以检查哪个点是多边形的 inside/outside。
我将使用外面的来显示多边形边的测量文本,例如 2cms
Click to see Visuals
旋转四分之一圈很容易:如果您有一个坐标为 (x, y)
的矢量,并将其逆时针旋转四分之一圈,则新矢量的坐标为 (-y, x)
.
求垂线上的点(x5,y5),可以将点(x2,y2)以(mx,my)为中心逆时针旋转四分之一圈,这样:
x5 - mx = - (y2 - my)
y5 - my = x2 - mx
然后你可以通过重新归一化向量 (x5-mx, y5-my) 来选择你的两个点 (x3, y3) 和 (x4, y4) 以获得你想要的长度:
x4 - mx = (x5 - mx) * (2 cm) / ((x5-mx)**2 + (y5-my)**2)
y4 - my = (y5 - my) * (2 cm) / ((x5-mx)**2 + (y5-my)**2)
x3 - mx = (x5 - mx) * (-2 cm) / ((x5-mx)**2 + (y5-my)**2)
y3 - my = (y5 - my) * (-2 cm) / ((x5-mx)**2 + (y5-my)**2)
首先你得求边方程:
y - y1 = (y2-y1)/(x2-x1)*(x-x1)
y = (y2-y1)/(x2-x1) * x1 - (y2-y1)/(x2-x1) * x + y1
一旦你有了这样的等式y=mx+q
(y 和 x 是常数,所以你只关心找到 m 和 q)你就可以找到中间点
M((x1+x2)/2), (y1+y2)/2)
当您同时拥有方程式和中点时,您可以选择偏移量。现在只需在段
上找到与该偏移量对应的点
P1(mx + offset, my + (offset * m)) and P2(mx - offset, my - (offset * m))
where m is the one you found in the first equation
现在你有2分
要找出哪个在里面,哪个在外面,我们需要更多的数据。例如,您可以尝试平分角度以找到多边形 M1 的中点,并检查 P1 和 P2 之间的哪一个与 M1 有距离,以便:
if distance(P1, M1) < distance(M, M1) then P1 is inside
"if the distance between the point and the middle of the polygon is less than the distance between the middle of the polygon and the middle of the side then P1 is inside the polygon"
还有其他解决方案,但根据可用数据,我只能这样做。现在你只需要把这个解释变成代码
图例:
y -> equation constant
x -> equation constant
m -> line inclination
q -> intersection with axis (you really don't need it for this)
M -> middle point of the side mx, my -> coordinates of middle point of the side
P1 -> point on the line with positive offset
P2 -> point on the line with negative offset
M1 -> middle point of the polygon
您没有指定语言,但几乎所有语言都有 atan2 function。
canvas.width = window.innerWidth - 10;
canvas.height = window.innerHeight - 10;
const ctx = canvas.getContext('2d');
const line = [canvas.width/2, canvas.height/2, 10, 10];
const pLen = 100; // Length of perpendicular
function drawOrto(line) {
// line vector
const dx = line[2] - line[0];
const dy = line[3] - line[1];
// center point
const mx = line[0] + dx / 2;
const my = line[1] + dy / 2;
const atan = Math.atan2(dy, dx);
// perpendicular vector
const pdx = - pLen * Math.sin(atan);
const pdy = pLen * Math.cos(atan);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Line
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.moveTo(line[0], line[1]);
ctx.lineTo(line[2], line[3]);
ctx.stroke();
// Perpendicular (draw vector both sides from center)
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(mx - pdx / 2, my - pdy / 2);
ctx.lineTo(mx + pdx / 2, my + pdy / 2);
ctx.stroke();
// Dots
ctx.fillStyle = 'red';
ctx.fillRect(line[0] - 1, line[1] - 1, 3, 3);
ctx.fillRect(line[2] - 1, line[3] - 1, 3, 3);
ctx.fillStyle = 'yellow';
ctx.fillRect(mx - 1, my - 1, 3, 3);
ctx.fillStyle = 'green';
ctx.fillRect(mx - pdx / 2 - 1, my - pdy / 2 - 1, 3, 3);
ctx.fillRect(mx + pdx / 2 - 1, my + pdy / 2 - 1, 3, 3);
}
drawOrto(line);
canvas.onmousemove = e => {
line[2] = e.offsetX;
line[3] = e.offsetY;
drawOrto(line);
}
<canvas id=canvas></canvas>
我有一个角度为 A 的不规则多边形 (x1,y1) (x2,y2) 的边和边的中点 (mx, my)。
我需要在 A 穿过 (mx, my) 的垂线上找到两个点 (x3,y3) 和 (x4,y4),并有一些偏移。这样我就可以检查哪个点是多边形的 inside/outside。
我将使用外面的来显示多边形边的测量文本,例如 2cms
Click to see Visuals
旋转四分之一圈很容易:如果您有一个坐标为 (x, y)
的矢量,并将其逆时针旋转四分之一圈,则新矢量的坐标为 (-y, x)
.
求垂线上的点(x5,y5),可以将点(x2,y2)以(mx,my)为中心逆时针旋转四分之一圈,这样:
x5 - mx = - (y2 - my)
y5 - my = x2 - mx
然后你可以通过重新归一化向量 (x5-mx, y5-my) 来选择你的两个点 (x3, y3) 和 (x4, y4) 以获得你想要的长度:
x4 - mx = (x5 - mx) * (2 cm) / ((x5-mx)**2 + (y5-my)**2)
y4 - my = (y5 - my) * (2 cm) / ((x5-mx)**2 + (y5-my)**2)
x3 - mx = (x5 - mx) * (-2 cm) / ((x5-mx)**2 + (y5-my)**2)
y3 - my = (y5 - my) * (-2 cm) / ((x5-mx)**2 + (y5-my)**2)
首先你得求边方程:
y - y1 = (y2-y1)/(x2-x1)*(x-x1)
y = (y2-y1)/(x2-x1) * x1 - (y2-y1)/(x2-x1) * x + y1
一旦你有了这样的等式y=mx+q
(y 和 x 是常数,所以你只关心找到 m 和 q)你就可以找到中间点
M((x1+x2)/2), (y1+y2)/2)
当您同时拥有方程式和中点时,您可以选择偏移量。现在只需在段
上找到与该偏移量对应的点P1(mx + offset, my + (offset * m)) and P2(mx - offset, my - (offset * m))
where m is the one you found in the first equation
现在你有2分 要找出哪个在里面,哪个在外面,我们需要更多的数据。例如,您可以尝试平分角度以找到多边形 M1 的中点,并检查 P1 和 P2 之间的哪一个与 M1 有距离,以便:
if distance(P1, M1) < distance(M, M1) then P1 is inside
"if the distance between the point and the middle of the polygon is less than the distance between the middle of the polygon and the middle of the side then P1 is inside the polygon"
还有其他解决方案,但根据可用数据,我只能这样做。现在你只需要把这个解释变成代码
图例:
y -> equation constant
x -> equation constant
m -> line inclination
q -> intersection with axis (you really don't need it for this)
M -> middle point of the side mx, my -> coordinates of middle point of the side
P1 -> point on the line with positive offset
P2 -> point on the line with negative offset
M1 -> middle point of the polygon
您没有指定语言,但几乎所有语言都有 atan2 function。
canvas.width = window.innerWidth - 10;
canvas.height = window.innerHeight - 10;
const ctx = canvas.getContext('2d');
const line = [canvas.width/2, canvas.height/2, 10, 10];
const pLen = 100; // Length of perpendicular
function drawOrto(line) {
// line vector
const dx = line[2] - line[0];
const dy = line[3] - line[1];
// center point
const mx = line[0] + dx / 2;
const my = line[1] + dy / 2;
const atan = Math.atan2(dy, dx);
// perpendicular vector
const pdx = - pLen * Math.sin(atan);
const pdy = pLen * Math.cos(atan);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Line
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.moveTo(line[0], line[1]);
ctx.lineTo(line[2], line[3]);
ctx.stroke();
// Perpendicular (draw vector both sides from center)
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(mx - pdx / 2, my - pdy / 2);
ctx.lineTo(mx + pdx / 2, my + pdy / 2);
ctx.stroke();
// Dots
ctx.fillStyle = 'red';
ctx.fillRect(line[0] - 1, line[1] - 1, 3, 3);
ctx.fillRect(line[2] - 1, line[3] - 1, 3, 3);
ctx.fillStyle = 'yellow';
ctx.fillRect(mx - 1, my - 1, 3, 3);
ctx.fillStyle = 'green';
ctx.fillRect(mx - pdx / 2 - 1, my - pdy / 2 - 1, 3, 3);
ctx.fillRect(mx + pdx / 2 - 1, my + pdy / 2 - 1, 3, 3);
}
drawOrto(line);
canvas.onmousemove = e => {
line[2] = e.offsetX;
line[3] = e.offsetY;
drawOrto(line);
}
<canvas id=canvas></canvas>