30.3.15

Avanzando en programación_30.03_

Después de escribir la última entrada de como avanza el programa, me puse a solventar un error que no me gustaba nada, y era que al probar el programa, la pantalla del OpenGL estaba trabada, la intentaba mover y ponía "No responde", y solo cuando realizaba la estrella y tenía que volver a dibujar era cuando se movía al punto que le había indicado antes pero no había hecho.

Este fallo como ya me suponía era por utilizar el comando getch(), ya que ese comando espera a que pulses una tecla para continuar, y mientras se queda en ese punto y no atiende al resto del programa(al menos así es como lo entiendo), así que informé sobre como insertar números y letras con el teclado en opengl y encontré el comando glutKeyboardFunc(teclado), el cual utiliza la tecla presionada en la función teclado, la cual, tras unos cuantos intentos logré que funcionase como el getch() lo hacía.

Y a partir de este momento, para insertar los números lo hay que hacer teniendo la pantalla de opengl seleccionada y no la ventana de comandos.

Ese fue un problema menor comparado con el siguiente, el cual me estuvo rompiendo la cabeza más de dos días.

Resulta que, dado que en un futuro pretendo usar el mismo programa para hacer estrellas de diferente cantidad de puntas, intento usar en el máximo número de casos comandos en los que uso la variable tamanho, que ahora está igualada a 7, con lo cual, si cambiara el 7 por otro número me tendría que realizar estrellas de ese otro número.

El problema surge al intentar que el programa calcule las coordenadas de los vértices, que anteriormente los escribí a mano ayudándome del programa AutoCAD y tenía las siguientes:

#define P1 0,10
#define P2 8,6
#define P3 10,-2
#define P4 4,-9
#define P5 -4,-9
#define P6 -10,-2
#define P7 -8,6

y luego en la función que me dibuja las líneas tenía esto:

          switch(i){
                case 0:
                glBegin(GL_LINES);          //dibujar líneas
                glVertex2i(P1);                    //1er punto
                glVertex2i(P2);                    //2o punto
                glEnd();                              //terminar de dibujar
                break;

                case 1:
                glBegin(GL_LINES);          //dibujar líneas
                glVertex2i(P1);                    //1er punto
                glVertex2i(P3);                    //2o punto
                glEnd();                              //terminar de dibujar
                break;
... (hasta case 21)

La parte de los case no la adapté aún, pero si en parte, ya que ahora es del estilo:
         
 switch(i){
     case 0:
     glBegin(GL_LINES);                              //dibujar líneas
     glVertex2i(puntox[1],puntoy[1]);          //1er punto
     glVertex2i(puntox[2],puntoy[2]);          //2o punto
     glEnd();                                                  //terminar de dibujar     break;

     case 1:
     glBegin(GL_LINES);                              //dibujar líneas
     glVertex2i(puntox[1],puntoy[1]);          //1er punto
     glVertex2i(puntox[3],puntoy[3]);          //2o punto
     glEnd();                                                  //terminar de dibujar
     break;
...(igual hasta case 21)

el cambio está en que usar una variable(mas bien un define) pasé a usar 2 variables(mas bien dos arrays) para los vértices, y esto tuvo que ser así por la manera de calcularlos.



Después de buscar bastante sobre como hacerlo, mirar páginas sobre trigonometría (que a parte de un coseno o seno facilillo no había mirado desde la ESO), hacer mis apuntes en papel, etc... encontré esta pagina:
 http://www.wikivia.org/wikivia/images/3/3b/1.1.2.3._Intersecci%C3%B3n_de_dos_arcos_circulares.pdf

En la cual aparecen las fórmulas para averiguar I1 e I2 a partir de C1 y C2; C1 sería el centro de la estrella y C2 el punto anterior a I2.


Y me puse a ello, usando la librería math.h traducí las fórmulas a C++

int distancia=sqrt(pow(puntox[1]-centrox,2)+pow(puntoy[1]-centroy,2));
int acimut=atan((puntox[1]-centrox)/(puntoy[1]-centroy));
int beta=acos((pow(radio,2)+pow(distancia,2)-pow(radio2,2))/(2*radio*distancia));
puntox[2]=centrox+radio*sin(acimut+beta);
puntoy[2]=centrox+radio*cos(acimut+beta);

Pero no había hecho más que empezar, más tarde me di cuenta de que esos int en realidad debían ser double, y aún más tarde (muuuucho más tarde) me di cuenta de que las funciones de seno, coseno, etc no operan con grados sexagesimales sino con radianes, con lo cual creé otras dos variables para pasar de grados a radianes y viceversa:

    double rad=pi/180;  //pasar de grados a radianes
    double gra=180/pi;  //pasar de radianes a grados

Peeeero (otro pero, siempre hay peros) no tenía el radio 2, es decir, la distancia entre un punto y otro punto, y buscando y buscando encontré la siguiente página:
http://www.aritor.com/trigonometria/triangulo_trigonometria.html

Y así lo traducí a C++:

    double angul = 360/tamanho;
    double angulo=angul*rad;
    double radio2=(radio*sin(angulo/2))*2;

Lo de angul sobra, lo podía poner todo en angulo, pero lo dejé por si lo usaba en otra cosa.

Luego probé que tal funcionaba todo y voilá!! un desastre... NADA TENÍA SENTIDO!!

El proceso para pulir la función puntos fue largo, laborioso y desesperante, aunque también divertido(en parte) e instructivo.

Probando y probando salieron cosas de los más raras en pantalla, aquí algunos ejemplos:

Starmie, eres tú?
El diamante
7 puntas si, pero no en su sitio 
 Estas si que no están en su sitio
WTF!! 
Creo que hay un cubo de rubick muy parecido



Hasta que, después de aparecerme esta estrella con una combinación de lo más simple me paré un poco en ella y observé que la mayoría de las distancias entre puntos son correctas, pero estaban todos agolpados en el primer cuadrante(la imagen está recortada, es de la parte superior derecha de la pantallita), y al observar las coordenadas de los puntos y compararlas con las que tenía fijadas en los define, observé que la diferencia era muy pequeña, pero el punto 4, el maldito punto 4.... siempre me torcía los planes (y la estrella), pese a tener mis sospechas no sé porqué siempre a partir del punto 3 todo era muy raro.

En este caso la coordenada de la Y estaba cambiada de signo ( y algo variada si, lo sé), con lo cual, y tomando medidas drásticas que no creo que funcionen para una estrella de otro tamaño, decidí multiplicar la Y del punto 4 por -1, y hacer un espejo con los restantes puntos.

De modo que igualé los valores en Y del punto 2 y el 7, del 3 y el 6 y del 4 y el 5, y los valores en X los igualé pero multiplicándolos por -1, es decir, cambiándoles el signo, con lo cual la simetría estaba asegurada.

Eso es lo que muestra en iniciar, los puntos no están exactamente con las coordenadas perfectas, pero si que muy aproximadas, y ese es el trozo de programa que tantos problemas me dio, espero que al menos ayude a alguien que intente hacer algo parecido.

Aunque ahí lo oculté en la ventana de comandos, debajo de la estrella hice un rectángulo, lo siguiente que intentaré será que muestre ahí los números que voy insertando, así como la estrella al resolverla, e intentaré deshacerme de la ventana de comandos, espero que no sea muy complicado xD



26.3.15

Avanzando en programación_26.03_

A día de hoy ya puede dibujar ¡está vivo!, aunque le queda bastante por hacer;


Probando con algunas de 2ª generación que tengo apuntadas, y va bastante bien hasta ahí, dibuja la estrella perfectamente, dice si es complementaria o no, tanto la de salida como las de entrada (si lo son las dos de entrada la de salida también lo será),y solucioné algunos errores que daba al comenzar a dibujar, uno que me estubo fastidiando bastante era que solo me dibujaba 3 veces como máximo, le di muchas vueltas, busqué pero no aparecía nada específico, pregunté a amigos y al final logré solventarlo.

Se trataba que escribia la función glutPostRedisplay(); despues de glutIdleFunc(estrelas); en el main, y no me dibujaba cuando quería, en su lugar, metí el redisplay al principio de la funcion estrelas y cada vez que la vuelve a empezar me dibuja la nueva estrella.

Ahora estaba intentando sacar una ecuación para averiguar un punto basandose en otro punto, un radio y un ángulo. La trigonometría la tengo un poco abandonada, pero no me suena de haber realizado algo parecido. Eso sería para sacar los 7 vértices perfectos, con el mismo radio y equidistantes al hacer 360º/7.


Y eso es todo, como se puede observar aún tiene algunos errores, como que si pulso enter mientras pide insertar borra las palabras.

En este último caso, la estrella 1211111 dice que no es complementaria ( no lo es) pero el dibujo si lo es, ya que para cualquier estrella que solo tenga números entre el 1 y el 3 esa será su representación.

24.3.15

Avanzando en programación_24.03_

Hace ya un tiempo que quiero un programa para que complemente por sí solo las estrellas para no tener que hacer el cálculo (pese a que es una tontería, son muchas veces) continuamente a mano, así que, tras pedir infructuosamente a varias personas que entienden sobre programación, opté por aprender programación y hacérmelo yo mismo. El programa sería el siguiente:

http://zakuimposible.blogspot.com.es/2013/08/programa-estrellas-complementarias.html

A día de hoy hago como un diario de la evolución que lleva, y para estrellas de 7 puntas ya conseguí que funcionase correctamente:


Aún hay que pulir algunos detalles, como que al insertar los 7 números, los siguientes los escriba abajo automáticamente(en la segunda que inserté se me olvidó darle al enter, aún así aceptó los números para la siguiente) y algunas cosillas más, pero la suma, resta y ordenarlas lo hace perfectamente.

Hasta aquí estoy satisfecho, pero aún queda mucho por hacer, y me parece lo más complicado, y es la etapa de dibujar la estrella resultante, estoy utilizando la librería openGL y la verdad, hace unas semanas no tenía idea de lo que era, hace unos meses no sabía lo que significada int...

Así que pese a que por el momento me da más problemas de los que me resuelve seguiré intentando subsanarlos. Para llegar a mostrar una línea llevo unos días, y no es por cuestión de código, que lo puedo copiar de internet para probar, es por otros errores del compilador etc que tuve que mirar demasiados blogs y foros para arreglarlos.


Luego habría una tercera etapa, que sería la de guardar los datos en archivos como tablas. Y una cuarta que sería para adaptar el programa a estrellas de más puntas, supongo que esto último no es muy complicado, pero prefiero ver que dibuje antes de meterme con eso.

Y ya está, cuando dibuje volveré a publicar sus avances, espero que no sea dentro de un año ;)