2010-06-30 16 views
7

Quiero saber cómo obtener un ángulo de una línea A-B desde el eje horizontal X. Otras preguntas en SO lo hacen solo entre dos líneas. Soy consciente de que siempre puedo dibujar A-C de segunda línea y calcular, pero me pregunto si hay un método más rápido.obtener el ángulo de una línea desde el horizonte

EDIT: Estoy muy seguro de que no estoy haciendo una optimización prematura.

+2

Tenga cuidado con la optimización prematura. ¿Has perfilado el código? –

+1

No puedo entender los votos a la baja. ¿Es esta una pregunta tonta? o si es ofensivo? hmm .. – VOX

+1

@VOX - Publique sus resultados de generación de perfiles. Pruébese a sí mismo que necesita una solución más rápida. –

Respuesta

9

Puede usar atan para eso.

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

El eje x es en realidad una línea con la ecuación

y = 0

así que podría usar la solución que ya tiene.

+0

Estaba buscando un método más rápido (menos CPU) si hay alguno. – VOX

1

Si

  1. El ángulo es pequeño,
  2. se puede vivir con pequeñas imprecisiones, y
  3. Se puede utilizar el ángulo en radianes, no grados,

luego hay una solución rápida: bajo estas condiciones, puede suponer que tan (a) = a = atan (a), y por lo tanto simplemente omita la llamada atan().

+0

gracias por un buen punto. – VOX

+0

"tan (a) = a = atan (a)" Eh ... ¿qué? –

+0

@Bart van Heukelom: Sí, como escribí, esto no es exacto, pero es una buena aproximación para ángulos pequeños. E. g. tan (0.1) = 0.1003, tan (0.2) = 0.203 Por lo tanto, para ángulos en este rango, si no necesita precisión absoluta, puede ahorrar algo de esfuerzo de cálculo. – Frank

1

También podría usar arccosine, si su línea tiene el formato [r_x,r_y], donde r_x es el cambio en x y r_y es el cambio en y.

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

Es ligeramente más opaco, pero es básicamente la ley producto escalar:

angle = arccos (r . v) 

Dónde r y v son ambos vectores unitarios (vectores de longitud 1). En nuestro caso, v es el vector [1,0], yr es

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

con el fin de que sea un vector unitario.

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

Si necesita los cuatro cuadrantes, Atan2 es más adecuado que 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; 
} 
Cuestiones relacionadas