简体   繁体   English

如何在Javascript中找到SVG上两条直线(路径)之间的角度?

[英]How to find angle between two straight lines (paths) on a SVG in Javascript?

I have two straight lines as <path> in SVG canvas. 我在SVG画布中有两条直线作为<path> Using pixel coordinates of LineA (A1x, A1y) (A2x, A2y) and LineB (B1x, B1y) (B2x, B2y) how can I calculate the angle between these lines. 使用LineA (A1x, A1y) (A2x, A2y)和LineB (B1x, B1y) (B2x, B2y)像素坐标,如何计算这些线之间的角度。

I have below code which works for THREE points (it works for green cases in below image). 我有以下代码适用于三个点(它适用于下图中的绿色案例)。 It does not work when (A2x, A2y) != (B1x, B1y) . (A2x, A2y) != (B1x, B1y)时它不起作用。

How can I modify this formula to work even when lines are not joined. 即使没有连接线,如何修改此公式也能正常工作。

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);
}

图片

You can exploit Math.atan2 function with cross product and dot product of direction vectors for these segments. 您可以利用Math.atan2函数与这些段的交叉乘积和方向向量的点积。 Note the atan2 returns signed angle in range -Pi...Pi 注意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);

你想要P0-CP1-D代替P0-CP1-C :只需翻译其中一个段让DC重合: P1' = P1 - D + C (然后D' = C )。

finding the angle (@) between two lines: 找到两行之间的角度(@):

tan@ = (m1-m2)/(1+m1.m2) tan @ =(m1-m2)/(1 + m1.m2)

where m1 and m2 are the gradient of the lines respectively. 其中m1和m2分别是线的梯度。 In terms of JS: 就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))
}

After submitting my answer, I realize this is the same solution as the one provided by @YvesDaoust. 在提交我的答案后,我意识到这与@YvesDaoust提供的解决方案相同。 That answer is a more concise conceptual summary of the same approach I have fleshed out here with a JavaScript example. 这个答案是一个更简洁的概念性概述,我在这里用JavaScript示例充实了相同的方法。

The answer is fairly simple: 答案很简单:

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);
}

You can calculate the angle from scratch using trigonometry fundamentals. 您可以使用三角函数基础从头开始计算角度。 However, to make your life easier you can also just use the function you already have. 但是,为了让您的生活更轻松,您也可以使用您已有的功能。 First, just mathematically translate one line so that one of its end points coincides with one of the end points of the other line. 首先,只需在数学上平移一条线,使其一个端点与另一条线的一个端点重合。 There are four different ways of matching up one end point from each line, and each way will produce a potentially different angle measure. 有四种不同的方法可以匹配每条线的一个端点,每种方式都会产生一个可能不同的角度测量值。 However, this is no bigger of a dilemma than you having to figure out which angle you want of the four angles you get when you take each of the original untranslated line segments, extend each into an infinite line, and examine the four angles where those two lines intersect. 然而,当你取出每个原始的非翻译线段,将每个角度延伸到一个无限的线条,并检查那些角度时,你必须弄清楚你想要的四个角度,这不是一个两难的难题。两条线相交。

You need a function that takes 4 points as inputs, ie p0, p1, p2 and p3. 你需要一个4点作为输入的函数,即p0,p1,p2和p3。 However, just to make clear which points are being made coincidental, I've instead labeled them as p0, c0, p1 and c1, such that p0 and c0 are both being moved in such a way as to make c0 and c1 coincide, resulting in three points: p0new, p1 and c, the latter of which equals both c1 and c0new. 然而,为了弄清楚哪些点是巧合的,我把它们标记为p0,c0,p1和c1,这样p0和c0都以这样的方式移动,使得c0和c1重合,结果三点:p0new,p1和c,后者等于c1和c0new。

Update : Upon examining your original function more closely, I realize my discussion above of the choice of four possible angles may not be relevant with the exact function implementation you have written, as the order of points p0 and p1 does not matter for your function. 更新 :在仔细检查原始函数后,我意识到我上面讨论的四个可能角度的选择可能与您编写的确切函数实现无关,因为点p0和p1的顺序对您的函数无关紧要。 You could rewrite your original function, perhaps using some of the concepts from the other answers, to be able to more fully control which angle you get as a result, if that's really what you want. 您可以重写原始函数,也许使用其他答案中的一些概念,以便能够更完全地控制您获得的角度,如果这真的是您想要的。 In any case, the general concept behind my answer holds: if you already have a function that calculates an angle between 3 points (with whatever limitations the algorithm has), you can use the same function on two disconnected line segments by simply translating one so that two end points coincide and then using the same function (again, with whatever limitations the algorithm still has). 在任何情况下,我的答案背后的一般概念都有:如果你已经有一个计算3点之间角度的函数(无论算法有什么限制),你可以在两个断开的线段上使用相同的函数,只需简单地翻译一个两个端点重合,然后使用相同的功能(同样,算法仍有任何限制)。

 function find_angle(p0,p1,c) { var p0c = Math.sqrt(Math.pow(cx-p0.x,2)+ Math.pow(cy-p0.y,2)); var p1c = Math.sqrt(Math.pow(cx-p1.x,2)+ Math.pow(cy-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} ) ); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM