如何在 Javascript 中的 SVG 上找到两条直线(路径)之间的角度?
How to find angle between two straight lines (paths) on a SVG in Javascript?
我在 SVG canvas 中有两条直线 <path>
。使用 LineA (A1x, A1y) (A2x, A2y)
和 LineB (B1x, B1y) (B2x, B2y)
的像素坐标如何计算这些线之间的角度。
我有以下适用于三点的代码(适用于下图中的绿色案例)。 (A2x, A2y) != (B1x, B1y)
.
时无效
如何修改此公式,使其即使在行未连接时也能正常工作。
function find_angle(p0,p1,c) {
var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
Math.pow(c.y-p0.y,2));
var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
Math.pow(c.y-p1.y,2));
var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
Math.pow(p1.y-p0.y,2));
var angle = Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
return angle * (180 / Math.PI);
}
您可以利用 Math.atan2 函数与这些段的方向向量的叉积和点积。注意范围 -Pi...Pi
中的 atan2 returns 符号角
//find vector components
var dAx = A2x - A1x;
var dAy = A2y - A1y;
var dBx = B2x - B1x;
var dBy = B2y - B1y;
var angle = Math.atan2(dAx * dBy - dAy * dBx, dAx * dBx + dAy * dBy);
if(angle < 0) {angle = angle * -1;}
var degree_angle = angle * (180 / Math.PI);
求两条线之间的角度 (@):
tan@=(m1-m2)/(1+m1.m2)
其中 m1 和 m2 分别是线条的梯度。 JS方面:
var m1 = (A1y-A2y)/(A1x-A2x)
var m2 = (B1y-B2y)/(B1x-B2x)
var angle
if(m1*m2==-1){
angle = Math.PI/2
}else{
angle = Math.atan((m1-m2)/(1+m1*m2))
}
您想要 P0-C
、P1-D
而不是 P0-C
、P1-C
:只需翻译其中一个片段让 D
和 C
重合:P1' = P1 - D + C
(然后D' = C
).
提交答案后,我意识到这与@YvesDaoust 提供的解决方案相同。这个答案是对我在这里用 JavaScript 示例充实的相同方法的更简洁的概念性总结。
答案很简单:
function find_disconnected_angle(p0,c0, p1,c1) {
return find_angle({x:p0.x-c0.x+c1.x,y:p0.y-c0.y+c1.y},p1,c1);
}
您可以使用三角学基础从头开始计算角度。但是,为了让您的生活更轻松,您也可以只使用已有的功能。首先,只需对一条线进行数学平移,使其端点之一与另一条线的端点之一重合。有四种不同的方法可以匹配每条线的一个端点,每种方法都会产生一个可能不同的角度测量值。然而,这并不比你必须找出你想要的四个角度中的哪个角度更难,当你将每个原始未翻译的线段延伸成一条无限线,并检查这些角度所在的四个角度时两条线相交。
您需要一个以 4 个点作为输入的函数,即 p0、p1、p2 和 p3。然而,为了弄清楚哪些点是巧合的,我将它们标记为 p0、c0、p1 和 c1,这样 p0 和 c0 都以使 c0 和 c1 重合的方式移动,结果在三个点中:p0new、p1 和 c,后者等于 c1 和 c0new。
更新:在更仔细地检查您的原始函数后,我意识到我上面关于选择四种可能角度的讨论可能与您编写的确切函数实现无关,因为点 p0 和 p1 的顺序对您的功能无关紧要。您可以重写您的原始功能,也许使用其他答案中的一些概念,以便能够更完全地控制您获得的角度,如果这确实是您想要的。无论如何,我的答案背后的一般概念是:如果你已经有一个函数来计算 3 点之间的角度(无论算法有什么限制),你可以通过简单地平移一个所以在两个断开的线段上使用相同的函数两个端点重合,然后使用相同的函数(同样,算法仍然存在任何限制)。
function find_angle(p0,p1,c) {
var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
Math.pow(c.y-p0.y,2));
var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
Math.pow(c.y-p1.y,2));
var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
Math.pow(p1.y-p0.y,2));
var angle = Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
return angle * (180 / Math.PI);
}
function find_disconnected_angle(p0,c0, p1,c1) {
return find_angle({x:p0.x-c0.x+c1.x,y:p0.y-c0.y+c1.y},p1,c1);
}
console.log(
find_angle(
{x: 7, y: 2},
{x: 7, y: 7},
{x: 2, y: 2}
)
);
console.log(
find_disconnected_angle(
{x: 27, y: 42},
{x: 22, y: 42},
{x: 7, y: 7},
{x: 2, y: 2}
)
);
我在 SVG canvas 中有两条直线 <path>
。使用 LineA (A1x, A1y) (A2x, A2y)
和 LineB (B1x, B1y) (B2x, B2y)
的像素坐标如何计算这些线之间的角度。
我有以下适用于三点的代码(适用于下图中的绿色案例)。 (A2x, A2y) != (B1x, B1y)
.
如何修改此公式,使其即使在行未连接时也能正常工作。
function find_angle(p0,p1,c) {
var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
Math.pow(c.y-p0.y,2));
var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
Math.pow(c.y-p1.y,2));
var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
Math.pow(p1.y-p0.y,2));
var angle = Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
return angle * (180 / Math.PI);
}
您可以利用 Math.atan2 函数与这些段的方向向量的叉积和点积。注意范围 -Pi...Pi
//find vector components
var dAx = A2x - A1x;
var dAy = A2y - A1y;
var dBx = B2x - B1x;
var dBy = B2y - B1y;
var angle = Math.atan2(dAx * dBy - dAy * dBx, dAx * dBx + dAy * dBy);
if(angle < 0) {angle = angle * -1;}
var degree_angle = angle * (180 / Math.PI);
求两条线之间的角度 (@):
tan@=(m1-m2)/(1+m1.m2)
其中 m1 和 m2 分别是线条的梯度。 JS方面:
var m1 = (A1y-A2y)/(A1x-A2x)
var m2 = (B1y-B2y)/(B1x-B2x)
var angle
if(m1*m2==-1){
angle = Math.PI/2
}else{
angle = Math.atan((m1-m2)/(1+m1*m2))
}
您想要 P0-C
、P1-D
而不是 P0-C
、P1-C
:只需翻译其中一个片段让 D
和 C
重合:P1' = P1 - D + C
(然后D' = C
).
提交答案后,我意识到这与@YvesDaoust 提供的解决方案相同。这个答案是对我在这里用 JavaScript 示例充实的相同方法的更简洁的概念性总结。
答案很简单:
function find_disconnected_angle(p0,c0, p1,c1) {
return find_angle({x:p0.x-c0.x+c1.x,y:p0.y-c0.y+c1.y},p1,c1);
}
您可以使用三角学基础从头开始计算角度。但是,为了让您的生活更轻松,您也可以只使用已有的功能。首先,只需对一条线进行数学平移,使其端点之一与另一条线的端点之一重合。有四种不同的方法可以匹配每条线的一个端点,每种方法都会产生一个可能不同的角度测量值。然而,这并不比你必须找出你想要的四个角度中的哪个角度更难,当你将每个原始未翻译的线段延伸成一条无限线,并检查这些角度所在的四个角度时两条线相交。
您需要一个以 4 个点作为输入的函数,即 p0、p1、p2 和 p3。然而,为了弄清楚哪些点是巧合的,我将它们标记为 p0、c0、p1 和 c1,这样 p0 和 c0 都以使 c0 和 c1 重合的方式移动,结果在三个点中:p0new、p1 和 c,后者等于 c1 和 c0new。
更新:在更仔细地检查您的原始函数后,我意识到我上面关于选择四种可能角度的讨论可能与您编写的确切函数实现无关,因为点 p0 和 p1 的顺序对您的功能无关紧要。您可以重写您的原始功能,也许使用其他答案中的一些概念,以便能够更完全地控制您获得的角度,如果这确实是您想要的。无论如何,我的答案背后的一般概念是:如果你已经有一个函数来计算 3 点之间的角度(无论算法有什么限制),你可以通过简单地平移一个所以在两个断开的线段上使用相同的函数两个端点重合,然后使用相同的函数(同样,算法仍然存在任何限制)。
function find_angle(p0,p1,c) {
var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
Math.pow(c.y-p0.y,2));
var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
Math.pow(c.y-p1.y,2));
var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
Math.pow(p1.y-p0.y,2));
var angle = Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
return angle * (180 / Math.PI);
}
function find_disconnected_angle(p0,c0, p1,c1) {
return find_angle({x:p0.x-c0.x+c1.x,y:p0.y-c0.y+c1.y},p1,c1);
}
console.log(
find_angle(
{x: 7, y: 2},
{x: 7, y: 7},
{x: 2, y: 2}
)
);
console.log(
find_disconnected_angle(
{x: 27, y: 42},
{x: 22, y: 42},
{x: 7, y: 7},
{x: 2, y: 2}
)
);