
...el poder de lo simple...
Marzo.4.2010
Cómo graficar
una curva ?
Para
dibujar una curva expresada por una ecuación algebraica en un espacio
bidimensional o plano de coordenadas cartesianas deben generarse
valores para una de las variables y con base en ellos calcular los
valores de la otra variable.
Así por ejemplo, si se tiene una función de la forma general
y = f(x)
se generan valores para la variable independiente x
y ellos se aplican a la función f para
encontrar los valores correspondientes de la variable
dependiente y
Luego el grupo de pares ordenados (x,
y)
o puntos se unen mediante segmentos de rectas entre ellos
formando un trazo visible.
Debe
tenerse en cuenta que los pares de valores generados no necesariamente
están en el rango de pixeles referenciables en una ventana del
computador por lo que usualmente deben ser normalizados, es decir deben
ser adecuados para ser contenidos en el espacio visible disponible.
Ésto se logra estableciendo proporción entre entre los rangos de los
valores generados y los rangos de los pixeles disponibles y luego
aplicacándola a cada par de manera que se conserven las relaciones
geométricas entre los puntos.
Llámense:
Xmin: El valor menor de las x
generadas
Xmax: El valor mayor de las x
generadas
Ymin: El valor menor de las y
generadas
Ymax: El valor mayor de las y
generadas
XPmax: El valor del
pixel extremo-izquierdo disponible para la gráfica
XPmax: El valor del
pixel extremo-derecho disponible para la gráfica
YPmin: El valor del
pixel extremo-superior disponible para la gráfica
YPmax: El valor del
pixel extremo-inferior disponible para la gráfica
Ahora es claro que deben formarse equivalencias entre los espacios
generados y disponibles:
el rango Xmax-Xmin generado debe dibujarse en el rango XPmax-XPmin
y
el rango Ymax-Ymin generado debe dibujarse en el rango YPmax-YPmin
Los demás datos generados deben ubicarse proporcionalmente para
conservar su relación geométrica.
Las proporciones px
y py serán
calculadas como:
XPmax-XPmin
--------------- = px
Xmax-Xmin
y
YPmax-YPmin
---------------- = py
Ymax-Ymin
La aplicación de esas proporciones harán que:
XPmax-XPmin = px
(Xmax-Xmin)
YPmax-YPmin = py
(Ymax-Ymin)
Por lo que
cada valor generado x afectado
por la proporción px
dará el valor en pixeles
cada valor generado y afectado
por la proporción py
dará el valor en pixeles
El algoritmo consistirá en:
1. Pedir el rango de las x que interesa Xmax, Xmin y la
cantidad de puntos deseados
2. Generar cada punto:
2a. Generar x
en el rango dado
2b. Generar y correspondiente
3. Pedir los extremos del espacio donde se desea dibujar XPmax, XPmin,
YPmax,YPmin
4. Calcular las proporciones px y
py
5. Normalizar los puntos: Transformar los pares (x,
y)
en (x*px, y*py)
6. Dibujar segmentos de línea recta entre los puntos
Nótese
que los pasos 2 y 5 significan hacer la operación para todos los
puntos, lo que en programación se logra mediante ciclos de
repetición de las mismas operaciones con valores distintos. Además
pueden ser unificados los dos tratamientos en un mismo ciclo dado que
ámbos hacen el mismo recorrido. Sintetizando y reorganizando los pasos
el algoritmo quedaría así:
1. Pedir el rango de las x que interesa Xmax, Xmin y la
cantidad de puntos deseados Npuntos
3. Pedir los extremos del espacio donde se desea dibujar XPmax, XPmin,
YPmax,YPmin
4. Calcular las proporciones px y
py
2. En cada punto:
2a. Generar x
en el rango dado
2b. Generar y correspondiente
5. Normalizar los puntos: Transformar
los pares (x,
y)
en (x*px, y*py)
6. Dibujar segmentos de línea recta
entre los puntos
Que en limpio queda asÍ:
1. Pedir el rango de las x que interesa Xmax, Xmin y la
cantidad de puntos deseados
2. Pedir los extremos del espacio donde se desea dibujar XPmax, XPmin,
YPmax,YPmin
3. Calcular las proporciones px y
py
4. En cada punto:
4a. Generar x
en el rango dado
4b. Generar y correspondiente
4c. Normalizar los puntos: Transformar
los pares (x,
y)
en (x*px, y*py)
4d. Dibujar segmentos de línea recta
entre los puntos
Surge una pregunta
....y cómo generar los diversos valores para la variable x ?
Una
forma es generarlos monotonicamente (monótonamente espaciados en el
rango [XPmin, XPmax]) pues se conoce el rago de las x
y la cantidad de puntos deseados por lo que es fácil calcular el tamaño
del paso (distancia o delta de las x)
entre las diversos valores de la x:
XPmax - XPmin
dx = ------------------
Npuntos
Si la variable x
parte del valor inferiror Xmin se le pueden ir agregando
deltas dx
y en Npuntos pasos llegará al valor XPmax
El algoritmo, ahora ya detallado quedaría así:
1. Pedir el rango de las x que interesa Xmax, Xmin y la
cantidad de puntos deseados Npuntos
2. Pedir los extremos del espacio donde se desea dibujar XPmax, XPmin,
YPmax,YPmin
3. Calcular las proporciones px y
py
4. Calcular paso o incrementos de la x:
dx
5. Iniciar la variable x
en Xmin
6. En cada punto:
6a. Generar x
en el rango dado, es decir incrementar la variable x en dx
6b. Generar y correspondiente
6c. Normalizar los puntos: Transformar
los pares (x,
y)
en (x*px, y*py)
6d. Dibujar segmentos de línea recta
entre los puntos
Dicho lo anterior utilizando el lenguaje Lexico
sería algo como:
tarea
{
/*Se
separa espacio en la RAM para las variables*/
los
objetos Xmax, Xmin, Ymax, Ymin, XPmax, XPmin, YPmax,YPmin, x,
y, px, py, dx, Npuntos, xo son cantidades
/*Se piden 9 datos por el teclado*/
entre Xmin,
Xmax, Ymin, Ymax, XPmin, XPmax, YPmin, YPmax, Npuntos
/*Se calculan las proporciones y el delta para las x*/
copie
(XPmax-XPmin)/(Xmax-Xmin) en
px
copie
(YPmax-YPmin)/(Ymax-Ymin) en
py
copie
(XPmax -
XPmin)/Npuntos en dx
/*Se inicia la variable en Xmin*/
copie
Xmin en x
/*Se ordena repetir una secuencia de instrucciones
condicionada por la expresión lógica*/
mientras
x
< Xmax haga:
{
copie x +
dx
en x,
xo
/* Genera nuevo valor en x y también guarda una copia en xo
*/
copie f(x)
en y
/* Genera el
correspondiente valor en y. REEMPLAZAR f(x)
por el caso particular */
copie xo * px en xo
/* Transforma el valor de x a la escala de las x en pixeles */
copie y
* py en y
/* Transforma el valor de y a la escala
de las y en pixeles */
muestre xo,
y
/* Se muestran los valores de xo
y y
en la escala de pixeles */
}
muestre "Ya se generaron los valores pero aún no se dibujan"
}
Obsérvese que se usa una variable auxiliar xo
con el fin de transformar solo la copia (copie xo * px en xo)
y preservar los valores sin transformación
de x
pues éstos son la base de la generación de los próximos. Si no
se hiciera así los valores x transformados
influirían en los sin transformar con una instrucción como copie
x
* px en
x.
Los pares ordenados o puntos base para la gráfica serán los valores
existentes cada vez en las variables (xo,
y)
Cómo dibujar los segmentos de línea recta entre la sucesión de
puntos o pares de valores existentes cada vez en (xo,
y)
?
Se presentarán dos formas:
La primera más simple (pero más restrictiva) utiliza una clase llamada Graficador
que previamente se ha programado, se ha almacenado y compilado para
formar el archivo riosur30.dll el cual
debe ser referenciado mediante la instrucción incluya
al principio del código para que el compilador busque allí los recursos
solicitados. Ella tiene definidos varios recursos que simplifican
la programación.
La segunda, menos intuitiva, exige más
conocimientos respecto a la plataforma .NET pero es más general pues
utiliza directamente los recursos que se usaron para crear la
clase Graficador
usada en la primera forma.
Primera forma:
La clase Graficador
que existe en el archivo riosur30.dll tiene
definidos entre sus atributos y comportamientos (ver éste
documento) los siguientes:
Atributos que tienen los objetos que se construyan con ésta
clase:
:
:
:
Comportamientos, métodos, algoritmos o mensajes que "entienden" los
objetos que se construyan con ésta clase:
Graficador:
Método constructor (algoritmo que al llamarse construye el objeto en la
RAM).
DibujeTrazo(
, ): Dibuja un trazo con base en dos
objetos dados de la clase ArrayList.
El primero debe contener las absisas o Xs y el segundo
las ordenadas o Ys.
Muéstrese:
Despliega la gráfica en una ventana.
:
Entonces se puede:
1. Crear un objeto:
el objeto g es un Graficador
2. Ordenarle al objeto g que DibujeTrazo
dándole dos objetos de tipo ArrayList que contengan las Xs y las Ys.
3. Ordenarle al objeto g que despliegue la gráfica: Muéstrese
Para cumplir con el ítem 2 deben crearse dos ArrayList y llevar a
ellos mediante el mensaje Add
los sucesivos valores Xs
y Ys
calculados:
los objetos GrupoX, GrupoY son ArrayList
Cada vez que se genere un par X
y Y se
agregan a los ArrayList con GrupoX y GrupoY utilizando el mensaje Add:
GrupoX.Add(X)
GrupoY.Add(Y)
Todo junto quedaría así:
{
/*Se
separa espacio en la RAM para las variables*/
los
objetos Xmax, Xmin, Ymax, Ymin, XPmax, XPmin, YPmax,YPmin, x,
y, px, py, dx, Npuntos, xo son cantidades
los
objetos GrupoX, GrupoY son ArrayList
/*Se piden 9 datos por el teclado*/
entre Xmin,
Xmax, Ymin, Ymax, XPmin, XPmax, YPmin, YPmax, Npuntos
/*Se calculan las proporciones y el delta para las x*/
copie
(XPmax-XPmin)/(Xmax-Xmin) en
px
copie
(YPmax-YPmin)/(Ymax-Ymin) en
py
copie
(XPmax -
XPmin)/Npuntos en dx
/*Se inicia la variable en Xmin*/
copie
Xmin en x
/*Se ordena repetir una secuencia de instrucciones
condicionada por la expresión lógica*/
mientras
x
< Xmax haga:
{
copie x +
dx
en x,
xo
/* Genera nuevo valor en x y también guarda una copia en xo
*/
copie f(x)
en y
/* Genera el
correspondiente valor en y. REEMPLAZAR f(x)
por el caso particular */
copie xo * px en xo
/* Transforma el valor de x a la escala de las x en pixeles */
copie
y
*
py en
y
/* Transforma el valor de y a la escala
de las y en pixeles */
GrupoX.Add(xo)
GrupoY.Add(y)
}
g.DibujeTrazo (doy
GrupoX, doy GrupoY)
g.Muéstrese
muestre "Ya se generaron los valores y se dibujó la gráfica"
}
Segunda forma
Ésta versión, a diferencia de la anterior, no utiliza riosur30.dll sino
directamente las clases de la plataforma .NET.
Para
dibujar un segmento de línea se necesita el punto origen y el punto
destino o sea que cada vez se requieren dos pares ordenados de valores,
es decir los dos puntos extremos del segmento. La dificultad reside en
que en la ejecución de la secuencia definida dentro del ciclo cada vez
el par (xo,
y)
se renueva y se pierden los dos valores anteriores. Ésto impone la
necesidad de tener otro par de variables (xant, yant) para
conservar el par de valores previo y que una vez utilizados se renueven
con los actuales que serán los futuros anteriores. También han de
iniciarse en los comienzos de los rangos de pixeles a utilizar.
Para dibujar se requiere una ventana, formulario o Form donde
se desplegará el contenido de un área, zona de la RAM para graficar o Graphics y
algunas herramientas como un lápiz o Pen de
un Color
determinado. A algunos de esos objetos han de enviarse mensajes
apropiados tales como Show (para
desplegar la ventana),......:
(en proceso oct.20.2009):
tarea
{
/*Se
separa espacio en la RAM para las variables*/
los
objetos Xmax, Xmin, Ymax, Ymin, XPmax, XPmin, YPmax,YPmin, x,
y, px, py, dx, xant, yant, Npuntos, xo son cantidades
/*Se piden 9 datos por el teclado*/
entre Xmin,
Xmax, Ymin, Ymax, XPmin, XPmax, YPmin, YPmax, Npuntos
/*Se calculan las proporciones y el delta para las x*/
copie
(XPmax-XPmin)/(Xmax-Xmin) en
px
copie
(YPmax-YPmin)/(Ymax-Ymin) en
py
copie
(XPmax -
XPmin)/Npuntos en dx
/*Se inicia la variable en Xmin*/
copie
Xmin en x,
xant
copie Ymin en yant
/*Se ordena repetir una secuencia de instrucciones
condicionada por la expresión lógica*/
mientras
x
< Xmax haga:
{
copie x +
dx
en x,
xo
/* Genera nuevo valor en x y también guarda una copia en xo
*/
copie f(x)
en y
/* Genera el
correspondiente valor en y. REEMPLAZAR f(x)
por el caso particular */
copie xo * px en xo
/* Transforma el valor de x a la escala de las x en pixeles */
copie y
* py en y
/* Transforma el valor de y a la escala
de las y en pixeles */
}
muestre "Ya se generaron los valores pero aún no se dibujan"
}