2010-06-30 4 views
7

Ich möchte wissen, wie man einen Winkel einer Linie A-B von der horizontalen Achse X erhält. Andere Fragen in SO tun das nur zwischen zwei Linien. Ich bin mir bewusst, dass ich immer die zweite Linie A-C zeichnen und berechnen kann, aber ich frage mich, ob es eine schnellere Methode gibt.bekomme Winkel einer Linie vom Horizont

EDIT: Ich bin mir sehr sicher, dass ich nicht eine vorzeitige Optimierung mache.

+2

Vorsicht vor vorzeitiger Optimierung. Haben Sie den Code profiliert? –

+1

Ich kann die Down-Stimmen nicht verstehen. Ist das eine dumme Frage? oder ist es beleidigend? hmm .. – VOX

+1

@VOX - Veröffentlichen Sie Ihre Profilergebnisse. Beweisen Sie sich selbst, dass Sie eine schnellere Lösung benötigen. –

Antwort

9

Sie können atan dafür verwenden.

angle = atan((By-Ay)/(Bx-Ax)) 
0

Die x-Achse ist eigentlich eine Linie mit der Gleichung

y = 0

so könnte man die Lösung, die Sie bereits haben verwenden.

+0

Ich suchte nach schneller (weniger cpu) Methode, wenn es welche gibt. – VOX

1

Wenn

  1. Der Winkel klein ist,
  2. Sie mit kleinen Ungenauigkeiten leben können, und
  3. Sie können den Winkel in Radiant verwenden und nicht Grad,

dann gibt es eine schnelle Lösung: Unter diesen Bedingungen können Sie annehmen, dass tan (a) = a = atan (a), und daher den atan() -Aufruf einfach weglassen.

+0

danke für einen guten Punkt. – VOX

+0

"tan (a) = a = atan (a)" Äh ... was? –

+0

@Bart van Heukelom: Ja, wie ich schrieb, das ist nicht genau, aber eine gute Näherung für kleine Winkel. E. g. tan (0,1) = 0,1003, tan (0,2) = 0,203 Für Winkel in diesem Bereich können Sie also, wenn Sie keine absolute Genauigkeit benötigen, etwas Rechenaufwand sparen. – Frank

1

Sie könnten auch Arkuskosinus verwenden, wenn Sie Ihre Linie in Form [r_x,r_y] ist, wo r_x die Änderung in x ist und r_y ist die Änderung in y.

angle = arccos(r_x/(r_x*r_x + r_y*r_y)) 

Es ist leicht undurchsichtiger, aber es ist im Grunde das Skalarprodukt Gesetz:

angle = arccos (r . v) 

Wo r und v sind beide Einheitsvektoren (Vektoren der Länge 1). In unserem Fall ist v der Vektor [1,0] und r

[r_x,r_y]/(r_x^2+r_y^2) 

, um es ein Einheitsvektor zu machen.

6
private double Angulo(int x1, int y1, int x2, int y2) 
    { 
     double degrees; 

     // Avoid divide by zero run values. 
     if (x2 - x1 == 0) 
     { 
      if (y2 > y1) 
       degrees = 90; 
      else 
       degrees = 270; 
     } 
     else 
     { 
      // Calculate angle from offset. 
      double riseoverrun = (double)(y2 - y1)/(double)(x2 - x1); 
      double radians = Math.Atan(riseoverrun); 
      degrees = radians * ((double)180/Math.PI); 

      // Handle quadrant specific transformations.  
      if ((x2 - x1) < 0 || (y2 - y1) < 0) 
       degrees += 180; 
      if ((x2 - x1) > 0 && (y2 - y1) < 0) 
       degrees -= 180; 
      if (degrees < 0) 
       degrees += 360; 
     } 
     return degrees; 
    } 
0

Wenn Sie alle vier Quadranten benötigen, ist Atan2 besser geeignet als Atan.

public static int GetAngleBetweenPoints(PointF pt1, PointF pt2) 
{ 
    float dx = pt2.X - pt1.X; 
    float dy = pt2.Y - pt1.Y; 

    int deg = Convert.ToInt32(Math.Atan2(dy, dx) * (180/Math.PI)); 
    if (deg < 0) { deg += 360; } 

    return deg; 
}