Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Buscando una formula matematica

Iniciado por Altair, 28 de Octubre de 2010, 10:29:53 AM

« anterior - próximo »

Altair

Buenas a todo el mundo,

ando liado con un proyecto propio que realizo en C/C++ y SDL y me he topado con un problema de formulas, segun parece es de trigonometria. Como un servidor es bastante malo (por no decir otra cosa xD) en temas de matematicas, pues a ver si me podeis hechar un cable. Si, ya se que es un inconveniente serio si te gusta la programacion, pero asi son las cosas, que le vamos a hacer. Detallo.

Tenemos un sistema 2D, donde las X es el eje horizontal y las Y el eje vertical. El eje X tiene su lado positivo a la derecha, y el eje Y hacia abajo.

Tenemos dos objetos, llamese Origen (Ox, Oy) y Destino (Dx, Dy), ambos pueden estar en cualquier coordenada. Tomando como punto de referencia Origen, hay que calcular el angulo que forma respecto a Destino.

El angulo crece en sentido antihorario, siendo algunos ejemplos:

Eje X positivo, 0 grados.
Diagonal derecha-arriba, 45 grados.
Eje Y negativo, 90 grados.

Ando mirando trigonometria por Google y Wikipedia, pero sigo sin verlo claro, la funcion seno no parece que sea la que busco, pero si alguna parecida a ella.


[EX3]

Buenas, Altair, bienvenido por estos lares :)

Pues justamente esto si lo tengo implementado en la dx_lib32 :P Te paso el codigo en Visual Basic 6.0 pero creo que no te sera problema alguno pasarlo a C ;)

Public Function MATH_GetAngle(X1 As Long, Y1 As Long, X2 As Long, Y2 As Long) As Single
    Dim tmp As Single
    tmp = CSng(MATH_Atan2(CDbl(X1) - CDbl(X2), CDbl(Y1) - CDbl(Y2)) * 180 / PI)
    If tmp < 0 Then
        MATH_GetAngle = 360 + tmp
    Else
        MATH_GetAngle = tmp
    End If
End Function

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

jmcots

Hola Altair,

espero que esto te ayude, te da el ángulo del vector v1 hasta v2 en sentido horario, teniendo en cuenta el sistema de coordenadas que comentas :


float radiants = atan2( v2.y, v2.x) - atan2( v1.y, v1.x);



The_Dragon_Ladis

#3
Estas cosas son de trigonometría básica, hay que tenerlas más o menos frescas. Ya no por programar, sino por conocimiento general.



Si el angulo que queremos calcular es z, entonces:

sin(z) = x / d
cos(z) = y / d
tan(z) = x / y

Siendo d = Raiz ( x^2 + y^2 ).

Podemos despejar el angulo de forma que nos quede:

z = arcsin( x / d )
z = arccos( y / d )
z = arctan( x / y )

Es preferible utilizar la arcotangente, ya que para los otros dos debemos calcular d, lo que conlleva más cálculos y hacer una raíz, por lo que es menos eficiente. En el caso del arcotangente solo tenemos que calcular x e y, que son simplemente:

x = B.x - A.x
y = B.y - B.y

Así al menos entiendes el concepto de como calcularlo, no solo usas el código que te dan. Espero haber sabido explicarme y que te haya servido de algo ^^

Pd: Ya podíais poner para inserta código TeX/LaTeX en el foro...

Pd2: Siento lo chustero de la imagen, la he hecho en 30 segundos en el Photoshop.

blau

Cita de: jmcots en 28 de Octubre de 2010, 06:17:51 PM
Hola Altair,

espero que esto te ayude, te da el ángulo del vector v1 hasta v2 en sentido horario, teniendo en cuenta el sistema de coordenadas que comentas :


float radiants = atan2( v2.y, v2.x) - atan2( v1.y, v1.x);




Eso esta bien, pero no se si es ese el angulo que se necesita, ese angulo es el que forman las rectas que pasan por el origen y por los puntos A y B   -> (A,0) (B,0)

si lo que se quiere es sacar el angulo de la recta que une dos puntos, el angulo que necesitas es el angulo que forma el vector director con respecto al eje de abcisas... lo digo porque para segun que cosas (¿disparos o rotaciones sobre el punto de origen?), es mas cómodo trabajar con este angulo.


float radiants = atan2( v2.y-v1.y, v2.x-v1.x);


The_Dragon_Ladis

Y yo diría que es hasta más eficiente porque cambias el hacer un ArcTan por hacer dos restas.

Pd: La respuesta de blau es lo que yo te he explicado pero en código ^_^

Altair

Buenas de nuevo,

estoy haciendo unas pruebas y me salen cifras de angulos que no me encajan con respecto a las posiciones.

Repito, el angulo crece en sentido antihorario.

Pogacha

De lo que se entera uno!

Al atan2 lo agregaron recien en el 2001 o sea que puede que recien aparecio en VC2003 o por ahí, yo personalmente no lo conocia.

¡Me hacen sentir bastante viejo y anticuado!

Hasta el VC6 (tal vez aun con VC7), la mejor forma era con un acos por que se tenia la maxima precision, pero lo del cuadrante lo tenias que hacer vos (lo cual no era mucho)

Desde luego tendré que actualizar mi librería matemática :X

Hechelion

#8
Cita de: Altair en 01 de Noviembre de 2010, 10:52:38 AM
Buenas de nuevo,

estoy haciendo unas pruebas y me salen cifras de angulos que no me encajan con respecto a las posiciones.

Repito, el angulo crece en sentido antihorario.


Podrías dar algunos ejemplos, tal como te han dado la solución del atan2(Y,X) está perfecto (Fiajte que es Y, X está al revés de lo clásica notación x,y). El hecho que sea antihorario es sólo una ilusión, ya que tu eje Y está invertido, en términos crudos el valor del angulo crece en sentido anti-horario con un eje Y normal, al invertir el eje Y automáticamente el ángulo va a crecer en sentido horario (asumiendo que usas siempre el punto 0,0 en la esquina superior izquierda.).

Edit. Si lo que quieres es un ángulo que crezca en sentido anti-horario, pero con un eje Y invertido, o en otras palabras el ángulo de depresión, entonces invierte el valor de Y.  atan2(-Y,X).

Altair

Cita de: Hechelion en 01 de Noviembre de 2010, 09:49:43 PM
Cita de: Altair en 01 de Noviembre de 2010, 10:52:38 AM
Buenas de nuevo,

estoy haciendo unas pruebas y me salen cifras de angulos que no me encajan con respecto a las posiciones.

Repito, el angulo crece en sentido antihorario.


Podrías dar algunos ejemplos, tal como te han dado la solución del atan2(Y,X) está perfecto (Fiajte que es Y, X está al revés de lo clásica notación x,y). El hecho que sea antihorario es sólo una ilusión, ya que tu eje Y está invertido, en términos crudos el valor del angulo crece en sentido anti-horario con un eje Y normal, al invertir el eje Y automáticamente el ángulo va a crecer en sentido horario (asumiendo que usas siempre el punto 0,0 en la esquina superior izquierda.).

Edit. Si lo que quieres es un ángulo que crezca en sentido anti-horario, pero con un eje Y invertido, o en otras palabras el ángulo de depresión, entonces invierte el valor de Y.  atan2(-Y,X).

Pues te cuento: Origen esta en el centro de la pantalla, y  en uno de los casos Destino aparecio arriba y a la izquierda. Segun las pruebas, Destino estaba a 60 grados respecto a Origen, lo cual es imposible porque ese angulo debe ser superior a 90 grados.

Repito los datos de referencia:

El eje X es el horizontal, el eje Y el vertical. El lado positivo de las X esta hacia la derecha, el lado positivo de las Y esta hacia abajo.

Eje X positivo, 0 grados.
Diagonal derecha-arriba, 45 grados.
Eje Y negativo, 90 grados.
Como se ve, en angulo crece en sentido antihorario.

Digamos que por "restricciones de proyecto" debe ser asi.

blau

Si usas esto para visualizar ¿te soluciona el problema?


alfacorregido = 2*Pi - alfaoriginal

Hechelion

#11
La verdad, te recomiendo que inviertas los valores de Y antes de pasarlos a la función.

Acá te dejo una imagen donde aparecen valores de ejemplo para los 4 cuadrantes  y sus resultados, tanto para un eje Y normal como para un eje Y invertido (el dibujo inferior), como ves, la función atan2(Y,X) devuelve bien los ángulos para todos los cuadrantes. Si sigues teniendo problemas, trata de colocar tu código, porque estoy pensando que tal vez tú problema no esté al usar Atan2, si no, que lo tengas al hacer el cambio de sistema de coordenadas para dejar el punto (0,0) en el centro de la pantalla.




EDIT:

Te dejo un dibujo de lo que creo quieres lograr, que sería el angulo respecto a un nuevo sistema de coordenadas.
En negro están lo valores clásicos, o sea, la posición de cada punto respecto a la esquina superior izquierda, en rojo, estarían los valores de los puntos para el nuevo sistema de coordenadas al medio de la pantalla.

Valores_rojos =  Posición_punto - Posición_nuevo_sistema

El Atan2, lo cálculo sobre el valor rojo, o sea, el valor que tiene el punto sobre le nuevo sistema de coordenadas e invierto el signo del eje Y



En resumen:
-Si el punto es (Px, Py)
-El nuevo sistema de coordenada está en (Sx, Sy)

Entonces, el ángulo lo sacas (Está llegar y usar):
Atan2( (Sy - Py), (Px - Sx) )



La diferencia respecto a las otras formulas es que tu preguntaste por el ángulo entre 2 puntos, cuando en realidad lo que quieres es el ángulo de un punto respeto a un nuevo sistema de coordenadas.

Avisa si te sirvió.
Saludos.

Altair

Veamos, mientras intento aclararme con todo esto, hay una cosa que no entiendo. En el cuadrante 1 y 2 has puesto:

atan2(1,1)=0.785=45º  (Esto en el primero)
atan2(1,-1)=2.356=135º  (Esto en el segundo)

Tanto el 0.785 como el 2.356, ¿como se convierten a grados?

blau

180 º = PI rad

1º = PI /180 rad

En Xna:

MathHelper.ToRadians(deg)

MathHelper.ToDegrees(rad)

Hechelion

#14
Habia escrito una respuesta, pero Blau se me adelanto. La única aclaración que agregaría es que por defecto toda función trigonometrica en un PC retorna el valor en Radianes (http://es.wikipedia.org/wiki/Radián)

Atan2(1,1) = 0.785 [Radaines]







Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.