简体   繁体   中英

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

I have two straight lines as <path> in SVG canvas. Using pixel coordinates of LineA (A1x, A1y) (A2x, A2y) and LineB (B1x, B1y) (B2x, B2y) how can I calculate the angle between these lines.

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) .

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. Note the atan2 returns signed angle in range -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)

where m1 and m2 are the gradient of the lines respectively. In terms of 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. That answer is a more concise conceptual summary of the same approach I have fleshed out here with a JavaScript example.

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. 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.

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. 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).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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