web-dev-qa-db-ja.com

勾配を計算せずに2本の線の間の角度を計算しますか? (Java)

L1とL2の2つのラインがあります。 2本の線の間の角度を計算したい。 L1にはポイント:{(x1, y1), (x2, y2)}があり、L2にはポイント:{(x3, y3), (x4, y4)}があります。

勾配を計算せずに、これら2つの線の間に形成される角度を計算するにはどうすればよいですか?私が現在抱えている問題は、時々水平線(x軸に沿った線)があり、次の式が失敗することです(ゼロ除算の例外)。

arctan((m1 - m2) / (1 - (m1 * m2)))

どこ m1およびm2は、それぞれライン1とライン2の勾配です。ゼロ除算の例外を発生させることなく2本の線の間の角度を計算できる数式/アルゴリズムはありますか?どんな助けも大歓迎です。

これは私のコードスニペットです:

// Calculates the angle formed between two lines
public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
    double slope1 = line1.getY1() - line1.getY2() / line1.getX1() - line1.getX2();
    double slope2 = line2.getY1() - line2.getY2() / line2.getX1() - line2.getX2();
    double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
    return angle;
}

ありがとう。

33
jNoob

_atan2_関数は、atanを扱う苦痛を緩和します。

double atan2(double y, double x)として宣言され、直交座標_(x,y)_を極座標_(r,theta)_から角度thetaに変換します

だから私はあなたのコードを

_public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
    double angle1 = Math.atan2(line1.getY1() - line1.getY2(),
                               line1.getX1() - line1.getX2());
    double angle2 = Math.atan2(line2.getY1() - line2.getY2(),
                               line2.getX1() - line2.getX2());
    return angle1-angle2;
}
_
95
brainjam

この場合、ドット積がおそらくより便利です。 ここ いくつかの便利なヘルパーを提供するJavaのジオメトリパッケージを見つけることができます。以下は2つの3Dポイント間の角度を決定するための計算です。あなたが始めました:

public static double computeAngle (double[] p0, double[] p1, double[] p2)
{
  double[] v0 = Geometry.createVector (p0, p1);
  double[] v1 = Geometry.createVector (p0, p2);

  double dotProduct = Geometry.computeDotProduct (v0, v1);

  double length1 = Geometry.length (v0);
  double length2 = Geometry.length (v1);

  double denominator = length1 * length2;

  double product = denominator != 0.0 ? dotProduct / denominator : 0.0;

  double angle = Math.acos (product);

  return angle;
}

幸運を!

13
Joseph Weissman
 dx1 = x2-x1; 
 dy1 = y2-y1; 
 dx2 = x4-x3; 
 dy2 = y4-y3; 
 
 d = dx1 * dx2 + dy1 * dy2; // 2つのベクトルのドット積
 l2 =(dx1 * dx1 + dy1 * dy1)*(dx2 * dx2 + dy2 * dy2)// 2乗長の積
 
 angle = acos(d/sqrt(l2)); 

2つのベクトルのドット積は、両方のベクトルの長さと角度のコサインに等しくなります。これはドット積を計算し、ベクトルの長さで除算し、逆余弦関数を使用して角度を復元します。

10
phkahler

Android座標系は誰かに役立つでしょう(ポイントを保存するためにAndroid PointFクラスを使用)

/**
 * Calculate angle between two lines with two given points
 *
 * @param A1 First point first line
 * @param A2 Second point first line
 * @param B1 First point second line
 * @param B2 Second point second line
 * @return Angle between two lines in degrees
 */

public static float angleBetween2Lines(PointF A1, PointF A2, PointF B1, PointF B2) {
    float angle1 = (float) Math.atan2(A2.y - A1.y, A1.x - A2.x);
    float angle2 = (float) Math.atan2(B2.y - B1.y, B1.x - B2.x);
    float calculatedAngle = (float) Math.toDegrees(angle1 - angle2);
    if (calculatedAngle < 0) calculatedAngle += 360;
    return calculatedAngle;
}

任意の象限に対して度単位の正の値を返します:0 <= x <360

あなたは私の ここでユーティリティクラス をチェックアウトできます

7
Dehimb

角度を取得する式はtan a = (slope1-slope2)/(1+slope1*slope2)です

あなたが使用しています:

tan a = (slope1 - slope2) / (1 - slope1 * slope2)

したがって、次のようになります。

double angle = Math.atan((slope1 - slope2) / (1 + slope1 * slope2));
3
AliveStar

これを確認してくださいPython code:

import math
def angle(x1,y1,x2,y2,x3,y3):

  if (x1==x2==x3 or y1==y2==y3):
    return 180
  else:
    dx1 = x2-x1
    dy1 = y2-y1
    dx2 = x3-x2
    dy2 = y3-y2
    if x1==x2:
      a1=90
    else:
      m1=dy1/dx1
      a1=math.degrees(math.atan(m1))
    if x2==x3:
      a2=90
    else:
      m2=dy2/dx2
      a2=math.degrees(math.atan(m2))
    angle = abs(a2-a1)
    return angle

print angle(0,4,0,0,9,-6)
0
Tirtha Chetry
dx1=x2-x1 ; dy1=y2-y1 ; dx2=x4-x3 ;dy2=y4-y3.

Angle(L1,L2)=pi()/2*((1+sign(dx1))* (1-sign(dy1^2))-(1+sign(dx2))*(1-sign(dy2^2)))
           +pi()/4*((2+sign(dx1))*sign(dy1)-(2+sign(dx2))*sign(dy2))
           +sign(dx1*dy1)*atan((abs(dx1)-abs(dy1))/(abs(dx1)+abs(dy1)))
           -sign(dx2*dy2)*atan((abs(dx2)-abs(dy2))/(abs(dx2)+abs(dy2)))
0

最初に、ブラケットが正しい順序になっていることを確認しますか?私は(間違っている可能性があります)それはこれであるべきだと思います:

   double slope1 = (line1.getY1() - line1.getY2()) / (line1.getX1() - line1.getX2());
   double slope2 = (line2.getY1() - line2.getY2()) / (line2.getX1() - line2.getX2());

第二に、0でdivに対してできることは2つあります。例外をキャッチして処理することができます

double angle;
try
{
    angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
catch (DivideByZeroException dbze)
{
    //Do something about it!
}

...または除数がゼロにならないことを確認できますbefore操作を試行します。

if ((1 - (slope1 * slope2))==0)
{
    return /*something meaningful to avoid the div by zero*/
}
else 
{
    double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
    return angle;
 }