2012-04-02 289 views
32

我需要計算我自己的Point類的兩點之間的角度度數,點a應該是中心點。Java:以度爲單位計算兩個點之間的角度

方法:

public float getAngle(Point target) { 
    return (float) Math.toDegrees(Math.atan2(target.x - x, target.y - y)); 
} 

測試1://返回45

Point a = new Point(0, 0); 
    System.out.println(a.getAngle(new Point(1, 1))); 

測試2://返回-90,預期:270

Point a = new Point(0, 0); 
    System.out.println(a.getAngle(new Point(-1, 0))); 

我如何轉換返回的結果爲0到359之間的數字?

+7

只注意到ATAN2參數是按相反的順序:必須ATAN2(Y,X) – alexm 2012-04-02 03:01:41

+0

我不知道哪裏出了問題,但我爲了能正常工作,相反的順序不會。 – Aich 2012-04-02 03:09:37

+2

您只能測量三點之間的角度。你可能會認爲'(0,0)'或'(min(x1,x2),min(y1,y2))'是其中一個點,但你不能在兩點之間畫一個角度。 – 2012-04-02 07:16:30

回答

58

,你可以添加以下內容:

public float getAngle(Point target) { 
    float angle = (float) Math.toDegrees(Math.atan2(target.y - y, target.x - x)); 

    if(angle < 0){ 
     angle += 360; 
    } 

    return angle; 
} 

順便說一下,你爲什麼要爲不使用雙重這裏?

+0

由於角度在瞬間只會低於0,所以我沒有理由在這裏使用while循環。 – Makoto 2012-04-02 02:43:22

+0

是的,我想你不必......編輯。 – 2012-04-02 02:44:23

+0

我在遊戲框架中將這種方法稱爲數百次。我想我有更多的性能,精度更低,我也不需要額外的數字。 – Aich 2012-04-02 02:52:18

1

Math.atan(double)的javadoc很清楚返回值的範圍可以從-pi/2到pi/2。所以你需要補償那個回報值。

22

我從johncarls解決方案開始,但需要調整它以獲得我需要的。 主要是,當角度增加時,我需要它順時針旋轉。我也需要0度指向北。他的解決方案讓我接近了,但我決定發佈我的解決方案以防萬一,以幫助其他人。

我已經添加了一些額外的註釋,以幫助解釋我對功能的理解,以防您需要進行簡單的修改。

/** 
* Calculates the angle from centerPt to targetPt in degrees. 
* The return should range from [0,360), rotating CLOCKWISE, 
* 0 and 360 degrees represents NORTH, 
* 90 degrees represents EAST, etc... 
* 
* Assumes all points are in the same coordinate space. If they are not, 
* you will need to call SwingUtilities.convertPointToScreen or equivalent 
* on all arguments before passing them to this function. 
* 
* @param centerPt Point we are rotating around. 
* @param targetPt Point we want to calcuate the angle to. 
* @return angle in degrees. This is the angle from centerPt to targetPt. 
*/ 
public static double calcRotationAngleInDegrees(Point centerPt, Point targetPt) 
{ 
    // calculate the angle theta from the deltaY and deltaX values 
    // (atan2 returns radians values from [-PI,PI]) 
    // 0 currently points EAST. 
    // NOTE: By preserving Y and X param order to atan2, we are expecting 
    // a CLOCKWISE angle direction. 
    double theta = Math.atan2(targetPt.y - centerPt.y, targetPt.x - centerPt.x); 

    // rotate the theta angle clockwise by 90 degrees 
    // (this makes 0 point NORTH) 
    // NOTE: adding to an angle rotates it clockwise. 
    // subtracting would rotate it counter-clockwise 
    theta += Math.PI/2.0; 

    // convert from radians to degrees 
    // this will give you an angle from [0->270],[-180,0] 
    double angle = Math.toDegrees(theta); 

    // convert to positive range [0-360) 
    // since we want to prevent negative angles, adjust them now. 
    // we can assume that atan2 will not return a negative value 
    // greater than one partial rotation 
    if (angle < 0) { 
     angle += 360; 
    } 

    return angle; 
} 
+1

而不是添加Pi/2 (不精確的近似值)轉換爲度數之前的弧度值,在將其轉換爲度數後加90,會更有意義。 – 2013-11-19 05:00:49

+0

你也可以做弧度嗎? **編輯:**沒關係 - 你只需刪除'Math.toDegrees'調用。 – starbeamrainbowlabs 2015-12-29 11:19:41

1

約像什麼:

angle = angle % 360; 
+1

但是..我們沒有te角! – Joehot200 2014-12-02 10:05:59

1
angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y)); 

現在的圓形價值觀的取向,保持在0和359之間的角度可以是:

angle = angle + Math.ceil(-angle/360) * 360 
1

基於Saad Ahmed's answer,在這裏是一種可以用於任何兩點的方法。

public static double calculateAngle(double x1, double y1, double x2, double y2) 
{ 
    double angle = Math.toDegrees(Math.atan2(x2 - x1, y2 - y1)); 
    // Keep angle between 0 and 360 
    angle = angle + Math.ceil(-angle/360) * 360; 

    return angle; 
} 
+0

這不是一個通用的方法 – FrankK 2017-09-28 13:15:51

+0

@FrankK我已經刪除了「generic」作爲描述符 – 2017-09-28 13:17:09