2017-02-10 63 views
3

我在SVG canvas中有兩條直線<path>。使用LineA (A1x, A1y) (A2x, A2y)和LineB的像素座標如何計算這些線條之間的角度。如何在Javascript中的SVG上找到兩條直線(路徑)之間的角度?

我有下面的代碼,它適用於三點(它適用於下圖中的綠色情況)。當(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); 
} 

Image

+0

向量在2D會給你這個答案很容易地使用或者圓點或交叉的產物。我更喜歡後者,因爲你有兩個角度可供選擇。 Cross產品允許您通過指定平面外方向來選擇哪一個。 – duffymo

+0

無論您使用(p0,p1,c)還是(p1,p0,c)調用,您當前的函數都會給出相同的結果。那真的是你想要的嗎? –

回答

1

可以利用與叉積和爲這些片段的方向向量的點積Math.atan2功能。注意ATAN2回報範圍-Pi...Pi

//find vector components 
var dAx = A2x - A1x; 
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); 
0

發現兩條線之間的角度(@)帶符號的角度:

黃褐色@ =(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)) 
} 
1

你想P0-CP1-D代替P0-CP1-C:只是翻譯的細分市場之一,讓DC不謀而合:P1' = P1 - D + C(當時D' = C)。

+1

我在回答我的答案後意識到,我用了更多概念性語言中提倡的相同方法。 –

0

提交我的答案後,我意識到這是與@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} 
 
) 
 
);

相關問題