Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





¿Estos dos algoritmos son correctos?

Iniciado por Altair, 18 de Julio de 2011, 09:32:30 AM

« anterior - próximo »

Altair

Muy buenas,

como de matematicas voy pez  ^_^' os pongo un poco en situacion, ya que no se si el algoritmo usado es incorrecto o me estoy liando por alguna otra parte.

Tenemos dos algoritmos, uno para calcular el angulo entre dos objetos (de Origen a Destino) y otro para hacer avanzar un objeto una distancia D en el angulo ANGLE. Estoy usando C/C++.

Los angulos usados son los mismos que teniamos en DIV2, los pongo aqui por si acaso.

0 grados, angulo hacia la derecha
+90 grados, angulo hacia arriba
+180 grados, angulo hacia la izquierda
+270 grados, angulo hacia abajo

estos angulos pueden tener valores negativos:

-90 grados, angulo hacia abajo
-180 grados, angulo hacia la derecha
... etc ...

El algoritmo para calcular en angulo es este, entity_id1 es el objeto origen y entity_id2 el objeto remoto.

double PI_detail;
int x1, y1, x2, y2;
float angulo;

PI_detail=3.141592;
x1=entity_id1->x;
y1=entity_id1->y;
x2=entity_id2->x;
y2=entity_id2->y;

angulo=atan2(x1 - x2, y1 - y2) * 180 / PI_detail;
if (angulo<0) { angulo += 360; }

Y luego tengo el algoritmo para hacer avanzar X pixels un objeto, que me ha dado dos sorpresas. La primera es que no puedo hacer avanzar el objeto 1 pixel porque no se mueve, deben ser como minimo 2. La segunda es que si la hago avanzar con angulo 0, y por tanto a la derecha, el movimiento es correcto, pero con un angulo de 90 grados (deberia ir hacia arriba), el objeto se mueve en diagonal abajo y a la izquierda.

El algoritmo de avance es este:

float radian;
float angulo;

angulo=entity_id->angle;
radian=(float)(3.1415926535897931/180)*angulo; // Pasamos el angulo a radianes.
entity_id->x=entity_id->x+(distance*cos(radian));
entity_id->y=entity_id->y+(distance*sin(radian));

Por ultimo, decir que no es imprescindible que se use el mismo sistema de angulos que div2 si es mejor usar otro sistema de angulos.

The_Dragon_Ladis

Supongo que te refieres a esto:


Si el angulo que quieres es ese, simplemente será arctan( ( B.x - A.x ) / ( B.y - A.y ) )

Altair

Por la forma que lo planteas, creo que es ese angulo.

Lo malo es que esta formula atan2((x2-x1), (y2-y1)) no me da valores correctos. En este momento estoy ejecutando el ejemplo y donde deberia ponerme +45 grados me pone 2.18 grados. Donde deberia marcarme 0 grados me pone 1.57 grados.

En cambio esta formula angulo=atan2((x2-x1), (y2-y1))  * 180 / PI_detail me da valores CASI correctos. Y digo CASI porque me da 0 grados hacia abajo y 90 grados a la derecha. Teoria: ¿sera algo del sistema de coordenadas?



The_Dragon_Ladis

Pues tiene toda la pinta. Revisa que el eje y sea el vertical y el x el horizontal. En algunos sistemas de coordenadas están cambiados o están implementados invertidos.

La función te da el valor en radianes. Por eso que la primera no te devuelve los valores que tu esperabas. Fijate en esta regla de tres:

Pi -> 180º
X -> Grados

Donde X es el valor devuelto por la función y Grados es su equivalencia en grados.

Grados = (X * 180) / Pi

Es la misma conversión que estás haciendo en tu segunda ecuación, y por eso los valores se parecen más a lo que esperas. Te lo explico para que sepas de donde viene y sepas el porqué :D

Pd: ¿Para cuando la función de escribir fórmulas en LaTeX en el foro? xD

Altair

Veamos, he conseguido desarrollar un sistema que parece funcionar

El eje X es horizontal y es positivo hacia la derecha
El eje Y es vertical y es positivo hacia abajo
Los 0 grados estan en el eje X positivo y crecen en sentido horario

   x=0
   y=0
   distancia=100
   angulo=80

Esto nos pone un objeto en las coordenadas X e Y indicadas, que avanzara 100 pixels con un angulo de 80 grados. Teniendo en cuenta como van los angulos, eso indica que va hacia abajo casi en linea recta, un poco a la derecha del eje Y positivo.

   Finales teoricos:
   x=0+100=100
   y=0+100=100

Teniendo en cuenta solamente las coordenadas X e Y y la distancia, las coordenadas destino quedarian asi.

   Lado X:
   100 -> 100%
   X -> 10 grados
   X= 100*10/100=1000/100=10
   x=0+10=10

Si avanzamos un 100%, recorremos 100 pixels.
El lado opuesto del angulo tiene 10 grados (recordemos que tenemos un giro de 80 grados, 90-80=10) y tenemos que calcular los pixels correspondientes.
Haciendo una regla de tres, nos da que tenemos una "ganancia" de 10 pixels.

   Lado Y:
   100 -> 100%
   Y -> 80 grados
   y=100*80/100=8000/100=80
   y=0+80=80

Muy parecido a lo de antes.
Si avanzamos un 100%, recorremos 100 pixels.
El lado opuesto del angulo tiene ahora 80 grados (90-10).
Hacemos regla de tres y sale una ganancia en Y de 80 pixels

   Coordenadas finales
   x=0+10=10
   y=0+80=80

A la coordenada X original (0) le sumamos la "ganancia" en X (10).
Hacemos lo mismo con la coordenada Y.

Lo que me tiene un tanto escamado es que 10+80 no suman 100 (la distancia que buscamos recorrer). Creo que eso indica que este metodo puede ser valido pero que falta pulirlo de alguna forma.

The_Dragon_Ladis

Es normal que la distancia no sea de 100. Primero porque 10 + 80 es 90, y lo segundo porque para calcular la distancia no se suma lo que mueves en x e y, sino tal que así:


Y la distancia d entre el punto Inicial y el Final sería (código en Mathematica, por si te sirve :P):
f[x_, y_] := N[Sqrt[(x^2) + (y^2) ]];

En tu caso concreto para x=10 e y=80 el resultado sería 80.6226.

El cálculo para dos puntos cualesquiera (ya que en el ejemplo suponemos que calculamos la distancia desde el origen de coordenadas) sería aplicando este calculo a la diferencia entre las coordenadas de cada punto.

Sqrt[(x1 - x2)^2 + (y1 - y2)^2]

Espero que sea eso lo que preguntas.

blau

Creo que tienes un cacao del bueno :P

¿He entendido reglas de tres entre angulos y distancias?

* Para avanzar con un angulo Alfa y una velocidad V lo mas sencilo es:

1. Obtener un vector director que tenga siga la direccion Alfa:   
           
           D.X = Cos(Alfa);
           D.Y = Sen(Alfa);

2. Este vector es unitario, su modulo es 1, mide 1 de longitud,... asi que si queremos avanzar con una velocidad V (pix / segundo) solo hay que multiplicarlo por V

          D = D * V; 

Lo he puesto usando Velocidad porque es lo mas logico para un juego... pej una nave para llegar de un punto a otro necesita un tiempo y pasar por varias posiciones.


3. Si sumamos D al punto inicial nos da un nuevo punto, equivalente a la distancia recorrida en 1 seg, si solo quieres recorrer un 10% de ese segundo, multiplicalo por 0.1f
           
         D = D * 0.1f;

4. Lo sumas al punto inicial y tienes el punto que querias....

* Para calcular un angulo con dos puntos, A y B:

1. Se calcula el vector director: V = B-A;
2. El angulo se obtiene mediante la Arcotangente:  Alfa = Atan2(V.Y, V.X);







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.