Heyyyyyyyyyyyyyyy

Aprende a programar microcontroladores en C... http://tecdigitaldelbajio.com/software-tarjeta.html

miércoles, 13 de enero de 2010

Ejemplo #16 Graficando la función seno en el celular

-->

Hoy se mostrará una aplicación practica de los arreglos, el ejemplo que se mostrará en este post tiene como objetivo graficar la función seno así que iniciemos.

La función seno

Como siempre se inicia recurriendo a la WikiPedia para conocer detalles de esta función da clic aquí para que veas el articulo de esta función. En la siguiente imagen se muestra la gráfica de la función, que a final de cuentas es lo que deseamos graficar en el celular:




Dos cosas, una la grafica en el eje de las y’s solo toma valores de 1 y de -1, y la otra, solo se graficará un ciclo completo de la función como en la figura, esto implica que se va a graficar en las x’s solo de 0 a 360 grados, esto se debe tomar en cuenta para realizar el programa.


Programa
Enseguida se da la explicación del código Java para que se muestre la grafica deseada, pero cabe mencionar que solo se muestra la parte que va en el método paint(), como crear los códigos para el proyecto ya se ha mencionado en los post anteriores a este, y creo yo, que ya no es necesario repetirlo.

Dibujando los ejes
Se inicia la gráfica dibujando los ejes coordenados, son simples dos líneas como se puede observar en la figura anterior. Para saber con exactitud el número de pixeles que tiene la pantalla del celular y además, para que el programa que se diseñe, funcione con cualquier tipo de pantalla así tenga más pixeles en una que en otra vamos a obtener el ancho y el alto en pixeles así:

ancho = getWidth();
alto = getHeight();
Obviamente que las variables que yo invente: ancho y alto, previamente se tuvieron que declarar de tipo entero. Recuerde las coordenadas que usa Java en la pantalla del celular son así: esquina superior izquierda (0,0), esquina inferior izquierda (0, alto), esquina superior derecha: (0, ancho) y esquina inferior derecha (ancho, alto)

Entonces basta con dos instrucciones que dibujan líneas para crear los ejes en color rojo así:

g.setColor(0xFF, 0x00, 0x00); // Rojo
g.drawLine(0, alto/2, ancho, alto/2); //eje x
g.drawLine(0, 0, 0, alto); //eje y

Si se ejecuta el programa así se verán los ejes así:
  

 
Bueno apenas se ve el eje de las Y que esta totalmente a la derecha, pero ahi esta, en el celular por supuesto que se ve mejor, por cierto el emulador que se está usando es el Sony Ericsson K750, cuyo ancho y alto en pixeles es de 176.

Ahora si se desea colocar letreros para denotar los ejes, se usa el método drawString, por ejemplo si se desea agregar el 1 y -1 al eje Y o si se desea agregar los grados al eje X podemos escribir así:

g.drawString("1", 4, 0, Graphics.TOP | Graphics.LEFT);
g.drawString("-1", 3, alto, Graphics.BOTTOM | Graphics.LEFT);
g.drawString("0", 4, alto/2, Graphics.TOP | Graphics.LEFT);
g.drawString("180", ancho/2-5, alto/2, Graphics.TOP | Graphics.LEFT);
g.drawString("360", ancho, alto/2, Graphics.TOP | Graphics.RIGHT);

cuyo resultado sería este:

Datos del eje X
Ahora si, vamos a realizar los cálculos de la función seno, se inicia con el eje x, esté es de lo más simple como se observa en la figura anterior, ya que son los grados que se usarán para la función seno y van desde 0 hasta 360, así que, si han pensado en un ciclo for que recorra desde 0 hasta 360, tienen toda la razón, el código sería el siguiente:

for (i=0; i<=360; i++ ) {

}
Lo que seguiría sería declarar un arreglo de 360 posiciones para que almacene cada uno de los números para posteriormente graficarlos, el arreglo, entonces almacenaría los números 0, 1, 2, 3…. 360, pero justo en este punto se ve un pequeño problema: Yo quiero graficar hasta 360 y el emulador del teléfono celular solo tiene en ancho 176 pixeles como ya lo mencioné, esté es un problema grave, porque un ciclo completo de la función seno va exactamente de 0 a 360 grados, si yo grafico la función está se vería así:


Casi se observa un semi-ciclo de la función, casi se grafica de 0 a 180 grados, esto porque solo se tienen 176 pixeles de ancho en el emulador, ahora si ya se ve el problema ¿verdad? Yo quiero que se grafique todo el ciclo de la función seno, pero no tengo los pixeles suficientes para ello.


La solución es bien simple, se hace un ajuste de lo más sencillo usando la llamada “regla de tres” es decir: “si 360 grados equivalen a 176 pixeles entonces cada grado equivale a X pixeles” al go parecido a esto:
360 -  176
1 grado - x
El resultado para 1 grado queda así:

x = ( 1 * 176) / 360 = 0.488888 pixeles
Entonces cada grado equivale a 0.4888 pixeles, algo que no es del todo practico por que los pixeles son números enteros, aún así esta aproximación es suficiente para mostrar la gráfica de la función seno como se verá un poco más adelante.

Basta con agregar la ecuación anterior al ciclo for mencionado arriba, para obtener en términos de pixeles cada uno de los 360 grados, por otro lado, cada uno de los grados (convertidos ahora en pixeles) se almacenaran en un arreglo de números enteros, entonces la ecuación en términos de las variables que se están manejando para el programa y dentro del ciclo for es la siguiente:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
}
El arreglo se declara de tipo entero, es llamado “x” y obviamente es de 360 posiciones. Pero vea la ecuación, es una división por lo que, como se vio, genera un número decimal, entonces pareciera que es un error, que se asigne un resultado decimal a un arreglo de enteros, pero no lo es del todo (al menos no en este ejemplo), se aprovecha la propiedad de Java de que, una división de números enteros se puede asignar a una variable de tipo entero perdiendo los decimales, esto debe sonar lógico puesto que lo que se desean son pixeles por que para trazar las líneas que dibujen la función seno se requieren números enteros solamente. Bueno espero me haya explicado.

Datos del eje Y
El eje Y contiene los valores de la función seno, recuerde la ecuación es así:

Y = sin x
Donde “x” son los grados, que en este punto ya están en el arreglo llamado x. Pero veamos que dice la documentación de Java acerca de la función seno (insisto, si no se ve bien da clic en la imagen para verla mejor):

Dos cosas se pueden ver de la documentación, una el ángulo debe estar en radianes y no en grados como se venía manejando y la otra, tanto el ángulo como el resultado deben ser de tipo double.


El primer punto se resuelve fácil convirtiendo cada uno de los 360 grados a radianes, esto se hace fácilmente con la función llamada “toRadians” que está en la clase Math, la función la puedes ver en la documentación de java, no la voy a mostrar pero ahí puedes verla, entonces una sentencia como la siguiente me convierte cada grado en radianes:

angRad = Math.toRadians(i);
Previamente se debe declarar la variable “angRad” de tipo double, con lo anterior se tiene el ángulo listo para la función seno, ahora solo se aplica la función y se asigna a un arreglo para formar los valores para el eje “y”, esto se hace así:

yt[i] = Math.sin(angRad);
El arreglo es llamado “yt” y debe ser declarado de tipo “double” para evitar pérdidas de decimales, y más en este punto puesto que el valor de la función seno es entre 1 y -1. Justo aquí tenemos un nuevo problema, el valor es entre 1 y -1, esto en términos de pixeles es nada, absolutamente nada, pero esto se resuelve bien fácil, una simple multiplicación puede “amplificar” la función de una forma proporcional, por ejemplo si se multiplica la función por 10 así:

yt[i] = 10 * Math.sin(angRad);
entonces “yt” almacenará valores de la función seno, ahora entre 10 y -10, el valor exacto para que la forma de onda se múltiplique y quede proporcionalmente a la pantalla del celular es: alto/2, entonces la ecuación final para “yt” es:

yt[i] = (alto/2) * Math.sin(angRad);
El ciclo for para los dos ejes queda así:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
    angRad = Math.toRadians(i); //grados a radianes
    yt[i] = (alto/2) * Math.sin(angRad); //datos del eje Y
}
Je je je , no me lo van a creer pero tenemos un nuevo problema, este igual de grave que los otros, con el ciclo anterior tendríamos los valores exactos del eje de las Y ¡¡pero estos valores son negativos¡¡¡ y me servirían a mi para graficar manualmente la función seno, con valores positivos y negativos pero a Java no le sirven por que las coordenadas de la pantalla del celular son positivas siempre. Vaya lio ¿verdad?.

La solución después de analizar un rato el problema es desplazar cada punto del arreglo “yt” cierta cantidad “hacia abajo” (recuerde que las coordenadas de java crecen hacia abajo), para ser exacto se desplaza en pixeles lo equivalente al valor de la variable alto/2, está es la ecuación exacta que me permite hacer lo que menciono:

y[i]=Math.abs(yt[i] - alto/2);
El desplazamiento se hace con una simple resta, la resta genera números negativos, para evitarlo se obtiene el valor absoluto de la resta con lo que se tendría ahora si puros valores positivos y estos valores no me la van a creer pero están ya en coordenadas de Java, listos para su graficación, cada valor se almacena en el arreglo de tipo entero llamado “y”, para este caso se debe agregar un conversor de tipo, puesto que la función del valor absoluto regresa un valor double, el conversor de tipo se agrega entre paréntesis así:

y[i]= (int) Math.abs(yt[i] - alto/2);
el (int) obliga a que el resultado se cambie a entero y se asigne al arreglo de enteros “y”, el código para el ciclo for queda entonces así:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
    angRad = Math.toRadians(i); //grados a radianes
    yt[i] = (alto/2) * Math.sin(angRad); //datos del eje Y
    y[i]= (int) Math.abs(yt[i] - alto/2);
}
Es posible eliminar el arreglo “yt” del ciclo, y declarar la variable de tipo double, puesto que este arreglo no se va a usar más, así que el código final para el ciclo for (ahora si es el código final se los prometo) queda así:

for (i=0; i<=360; i++ ) {
   x[i] = (ancho * i ) / 360; //datos del eje X
   angRad = Math.toRadians(i); //grados a radianes
   yt = (alto/2) * Math.sin(angRad); //datos del eje Y
   y[i]= (int) Math.abs(yt - alto/2);
}

Graficando la función
Para terminar el post, solo queda graficar los 360 puntos, puesto que ahora si los arreglos “y” y “x” tienen almacenadas las coordenadas y estas cooordenadas ya están en el mundo de java, la grafica se crea trazando pequeñas líneas de una coordenada a otra. Por ejemplo se traza una línea de la coordenada (x[0], y[0]) a la coordenada (x[1], y[1]), la siguiente línea sería de la coordenada (x[1], y[1]) a la coordenada (x[2], y[2]) y así sucesivamente, hasta terminar con la los 360 puntos.

Obviamente esto se realiza con un ciclo for de la siguiente manera:

for (i=0; i<=359; i++ ) {
    g.drawLine(x[i], y [i], x[i+1], y[i+1]);
}

El ciclo va de 0 a 359 ¿Por qué será? Y solo se requirió una simple instrucción que hace uso del método drawLine y listo, el resultado lo puedes ver en la siguiente imagen:

-->

Guau, si quedo bien ¿verdad? Ya para terminar agrego el video tutorial  para este ejemplo, no se muestra la creación de la clase para el Midlet, ni la clase que proviene de la clase Canvas, esto ya ha sido analizado en los post anteriores, por eso ya no lo inclui en el video.


Por si fuera poco anexo el código fuente, es la carpeta completita que genera Netbeans, esta en formato RAR da clic aqui para bajarlo, este realizada con el NetBeans 6.8, si no deseas el código fuente dando clic aqui puedes bajar el archivo JAR para que se lo envies via Bluetooth o USB a tu celualar, si soporta java verás la gráfica del seno sin lugar a dudas, yo lo probe en mi Sony Ericsson W595 y el resultado fue exactamente el mismo que el del emulador.
-->

Clic AQUI para leer más...!

jueves, 7 de enero de 2010

Arreglos



Continuando con la sintaxis de Java Micro Edition, hoy vamos a hablar de una de las estructuras de datos que se usan mucho en programación: los arreglos. Para iniciar nuestro estudio nos remitimos a la WikiPedia, la famosa enciclopedia libre, dando clic aquí puedes entrar al artículo de los arreglos, lo leemos y nos damos una idea de lo que es un arreglo, con esto me evito repetir la definición para que hacerlo si está al alcance de la mano, me interesa más analizar los arreglos pero usando código Java como se ve enseguida.


Arreglos en Java
Es posible crear un arreglo declarando una variable como el siguiente ejemplo:

int A[ ] = new int[10];
El arreglo se llama “A” es de tipo entero y tiene 10 espacios o lugares para almacenar datos, la información que se puede almacenar resulta obvia puros números enteros.

Veamos otro ejemplo, imagine el lector que se desea almacenar la altura, en metros de 20 personas, la opción más sencilla es declarar un arreglo de 20 posiciones y ahí almacenar los datos, que declarar 20 variables para los 20 datos, ahí se ve el uso de los arreglos, la declaración para lo que se pide es así:

float altura[ ] = new float[20];
La variable se llama “altura” y es de tipo float porque una persona puede medir 1.70 metros otra 1.67 y así sucesivamente, como son valores con punto decimal se usa la variable float.

Un ejemplo más imagine que se requiere almacenar el nombre de 40 personas, para realizarlo se declara un arreglo de tipo String así:

String nombres[ ] = new String[40];
Acceso a los datos de un arreglo
El arreglo creado con sentencias como las anteriores, reservan espacio de memoria, por ejemplo el arreglo “A” de enteros visto anteriormente reserva 10 espacios de memoria para almacenar datos, esto se puede imaginar como 10 celdas así:



El arreglo se llama “A” un solo nombre ¿entonces como puedo diferenciar las 10 celdas que hay? Sencillo, usando un número llamado índice, así la primer celda tiene el índice 0 y la última el índice 9, ahora el arreglo lo podemos visualizar como se muestra en la figura:



Escritura de datos en el arreglo
Para escribir datos basta con colocar el nombre del arreglo y entre “[ ]” el número de índice, por ejemplo si deseo almacenar el número 20 en la posición cero escribo así:

A[0] = 20;

Si deseo almacenar el -30 en la posición 8 lo hago así:

A[8] = -30;

Si deseo el número 290 en la celda 3 y el 100 en la 6 lo haría con estas instrucciones:

A[3] = 290;
A[6] = 100;
Con lo anterior puedo visualizar el arreglo así:






Lectura de datos del arreglo
Para leer lo que tiene un arreglo basta con asignarlo a una variable, en este caso la variable debe ser de tipo entero, por ejemplo si se desea saber que dato tiene la celda 6 escribo así:

x = A[6];
Previamente se debió declarar “x” de tipo “int”, después de que se ejecute la instrucción anterior “x” tendrá el valor de 100, ya que ese valor estaba previamente almacenado en el arreglo.

Escritura de datos usando ciclos for

Generalmente la lectura y escritura de un arreglo, por la gran cantidad de datos que hay se realiza con un ciclo for (aunque puede ser cualquier estructura repetitiva, pero el ciclo for se ajusta más)

Por ejemplo si se desea almacenar en el arreglo “A” los primeros 20 números a partir de 0, se podría escribir el código siguiente:

for (i = 0; i<=20; i++) {
  A[ i ] = i;
}

Recuerde en el ciclo for “ i ” toma los valores de 0, 1, 2, 3… 20.

Bueno aquí vamos a dejar esta lección, en la siguiente vamos a usar los arreglos en un ejemplo completo con todo y video-tutorial para que vea el lector donde se puede declarar el código del arreglo.




Clic AQUI para leer más...!