Procedimiento para el trazo de
gráficas
El pequeño intérprete de C cuenta con el conjunto de funciones que se muestran en la tabla 1 para realizar gráficas. Estas funciones permiten graficar con la sencillez que solía caracterizar a Turbo C con su BGI y a QBASIC. De hecho, las funciones trazadoras del sistema BGI incluidas aquí, simulan a QBASIC, ya que pueden operar en el sistema de coordenadas físicas y en el sistema de coordenadas lógicas. Por esta razón los tipos de datos que se suministran a dichas funciones son reales de doble precisión.
Función
|
Acción
|
Prototipo
|
bar |
Traza un rectángulo sin línea de contorno utilizando el
color de relleno establecido con setfillstyle. |
void bar(double left, double top,
double right, double bottom); |
circle |
Traza un círculo con centro en (x,y) y radio radio |
|
cleardevice |
Limpia la ventana de salida de gráficas empleando el color
de fondo |
|
clearviewport |
Limpia la región de graficación empleando el color de
fondo |
|
escala |
Establece un
sistema de coordenadas lógicas. (x1,y1) es la esquina inferior
izquierda. (x2,y2) es la esquina superior derecha. |
|
fillellipse |
Llena una elipse sin línea de contorno utilizando el color
de relleno establecido con setfillstyle. (xc,yc) es el centro de la elipse.
xradio y yradio son los semiejes horizontal y vertical, respectivamente |
void fillellipse(double
xc ,double yc ,double xradio , double
yradio); |
getmaxx |
Regresa la máxima abcisa física de la ventana de gráficas |
|
getmaxy |
Regresa la máxima ordenada física de la ventana de gráficas |
|
line |
Traza una línea entre los puntos (x1,y1) y (x2,y2) |
|
lineto |
Junta segmentos de
línea entre el último punto trazado y el punto (x,y) |
|
moveto |
Se traslada sin trazar a las coordenadas x,y |
|
outtextxy |
Traza una cadena de caracteres a partir de las coordenadas
(x,y) |
|
putpixel |
Traza un punto en (x,y) |
|
rectangle |
Traza un rectángulo. (x1,y1) es la esquina superior
izquierda y (x2,y2) la esquina inferior derecha. |
void rectangulo(double x1, double y1,
double x2, double y2); |
setcolor |
Establece el color de los trazos |
|
setbkcolor |
Establece el color de fondo empleado las funciones
cleardevice y clearviewport |
|
setfillstyle |
Establece el color de relleno usado por las funciones bar
y fillellipse |
void
setfillstyle(int patron, int color); El argumento patrón no se utiliza en esta
versión del interprete |
settextstyle |
Proporciona formato al texto |
void settextstyle (int font, int direccion, double dimension,); El argumento font no se utiliza en esta versión
del interprete |
settextjustify |
Proporciona alineación al texto |
|
setviewport |
Establece una región para graficar empleando coordenadas
físicas (x1,y1) es la esquina superior izquierda y (x2,y2) la esquina
inferior derecha. |
|
Tabla 1. Funciones que operan en la ventana de
gráficas
La invocación a cualquier función de la tabla 1 crea
automáticamente una ventana para la salida de gráficas. En contraste, la
invocación a cualquiera de las siguientes funciones: printf, puts o putch, crea
una ventana para la salida de texto. Ambas ventanas pueden estar presentes
paralelamente permitiendo la visualización simultánea de textos y graficas. Por
ejemplo, para colocar un mensaje tanto al centro de la ventana de gráficas como
al centro de la ventana de textos, se
hace lo siguiente:
main()
{
char mensaje[] =
"Hola";
// Abre la ventana
de gráficas y traza el mensaje "hola".
outtextxy(getmaxx() / 2,
getmaxy() / 2, mensaje);
// Abre la ventana para textos y coloca el mensaje
"hola".
gotoxy(40, 12);
puts(mensaje) ;
}
Las funciones getmaxx() y getmaxy() retornan la
máxima abcisa y ordenada del sistema de coordenadas físicas,
respectivamente. Estas coordenadas son relativas a la ventana de gráficas,
permitiendo, en el ejemplo anterior, colocar el texto al centro de ella. Es
importante recalcar que todas las funciones, con excepción de setviewport,
operan tanto en coordenadas físicas como en coordenadas lógicas, simulando a
este respecto el comportamiento de QBASIC. Por omisión todas la funciones
utilizan coordenadas físicas. Para modificar este comportamiento se debe, antes
de llamar a dichas funciones, invocar a la función escala, como se explica más
adelante. Las coordenadas físicas tienen como origen la esquina superior
izquierda de la ventana de gráficas como se muestra en la figura 1.
0, 0 getmaxx()
getmaxy()
Figura 1. Sistema de coordenadas físicas
Se dispone de 16 colores,
representados por números del 0 al 15 para efectuar trazos. Estos se presentan en
la tabla 2. Para poner la ventana de gráficas de un color determinado, se debe
invocar primero a la función setbkcolor y posteriormente a la función
cleardevice, así:
main()
{
setbkcolor(WHITE);
cleardevice(); // Ventana blanca
// Traza un punto negro al centro.
putpixel(getmaxx() / 2, getmaxy() / 2, BLACK);
}
La función cleardevice
borra la ventana gráfica con el color de fondo establecido mediante la función
setbkcolor.
Tabla 2. Colores disponibles para el trazo de
gráficas
El
trazo de gráficas se realiza mediante llamadas a las funciones putpixel, line,
lineto, moveto, rectangle, bar, circle y fillellipse. Los prototipos
de estas funciones se encuentran en la tabla 1. EL siguiente ejemplo ilustra el
uso de las funciones mencionadas:
main()
{
carita();
}
void carita()
{
setbkcolor(LIGHTGRAY);
cleardevice(); //
ventana gris claro
setcolor(BLUE);
circle(getmaxx() / 2, getmaxy() / 2, getmaxy() / 2);
// OJOS
setcolor(BROWN);
setfillstyle(1, BROWN);
fillellipse(getmaxx() / 2 - 150, getmaxy() / 2 - 100, 50,
50);// circulo relleno de color cafe
putpixel(getmaxx() / 2 - 150, getmaxy() / 2 - 100,
WHITE);
circle(getmaxx() / 2 + 150, getmaxy() / 2 - 100, 50);
putpixel(getmaxx() / 2 + 150, getmaxy() / 2 - 100,
WHITE);
// NARIZ
setcolor(LIGHTRED);
// línea
horizontal
line(getmaxx() / 2 - 50, getmaxy() / 2 + 100,
getmaxx() / 2 + 50, getmaxy() / 2 + 100);
lineto(getmaxx() / 2, getmaxy() / 2 - 50); // esta
línea junta la anterior con el nuevo punto
lineto(getmaxx()
/ 2 - 50, getmaxy() / 2 + 100); // lo mismo ésta
// BOCA
setfillstyle(1, 10);
bar(getmaxx() / 2 - 150, getmaxy() / 2 + 150, getmaxx() /
2 + 150, getmaxy() / 2 + 180);
}
La
salida de este pequeño programa se muestra en la figura 2.
Figura 2. Salida resultante de la invocación a
diversas primitivas
El
interprete sabe como funcionar con coordenadas lógicas, lo que permite simplificar
enormemente el trazo de gráficas hechas a escalas diferentes. Por ejemplo, para
graficar la función seno en el intervalo de 0 a 2PI, se requiere mapear los
valores de y que van desde -1 a +1, y los valores de x que se extienden de 0 a
2PI, a coordenadas físicas, que van de 0 a getmaxx(), y de 0 a getmaxy(),
respectivamente. Esta labor se logra muy elegantemente invocando, previo a las
funciones trazadoras, a la función escala. Esta función requiere cuatro
argumentos para invocarla. Su prototipo es como sigue:
void escala(double x1, double
y1, double x2, double y2);
Los
dos primeros argumentos constituyen las coordenadas lógicas mínimas del
problema que se está resolviendo, y las dos ultimas las coordenadas lógicas
máximas. Las primeras corresponden a la esquina inferior izquierda de la
ventana de gráficas y las segundas a la esquina superior derecha. Por ejemplo,
para graficar la función seno anteriormente mencionada primero se establece el
sistema de coordenadas lógicas asi:
escala(0, -1, 2 * PI, 1);
Lo
que permite obtener el sistema cartesiano siguiente:
Figura 3. Sistema de coordenadas lógico para graficar
a la función seno
Una vez invocada la
función escala, todas las primitivas, es decir line, lineto, moveto, etc,
operan con el sistema lógico de coordenadas, de manera similar a como solía
hacerlo QBASIC después de invocar a la función window de este compilador. Entonces, para graficar la función seno se
procede como sigue:
float x, y;
moveto(0, 0); //
nos movemos al punto de inicio sin trazar nada
for(x
= 0; x <= 2 * PI;x += .1)
{
y =
sin(x);
lineto(x,
y); // ahora juntamos segmentos de
línea
}
La labor de la función
escala consiste en mapear el sistema lógico de coordenadas al sistema físico de
coordenadas. Los cuatro argumentos de esta función son opcionales. Para
eliminar el sistema de coordenadas lógico simplemente se invoca a la función
escala sin argumentos, así:
escala();
Y ahora todas las
primitivas operan en el sistema de coordenadas físicas.
Se pueden trazar, si uno lo desea, varias gráficas en
la misma ventana pero en diferentes regiones independientes. La función
setviewport establece una región para graficar, de modo que una vez que se
invoca dicha función, la llamada a la función escala y a todas las funciones
que tienen salida gráfica, afectan únicamente la región especificada y no toda
la ventana. El prototipo de region es el siguiente:
void setviewport (int x1, int
y1, int x2, int y2, int clip);
Los cuatro primeros
argumentos son las coordenadas
físicas de la región, es decir, (x1, y1) es la esquina superior
izquierda y (x2, y2) la esquina inferior derecha. El quinto argumento es una
bandera. Un valor de 1 indica que la gráfica será cortada en los límites de la
región y un valor de 0 que la gráfica no será truncada. Los cinco argumentos de
esta función son opcionales. Para eliminar la región simplemente se invoca a
setviewport sin argumentos así:
setviewport();
Y ahora las funciones
operan en toda la ventana de gráficas.
Es importante destacar que
una vez creada una región para graficar, las coordenadas lógicas establecidas
con la función escala están referidas a dicha región. El siguiente ejemplo,
realiza dos gráficas de la función oscilatoria amortiguada representado por la
ecuación:
y = cos(wx)exp(-kx)
int main()
{
rectangle(200, 10, 400, 200);
setviewport(200,
10, 400, 200,1);
escala(0,
-1, 10, 1); // Se establece la escala
en la región anterior
setcolor(8);
line(0, 0, 10, 0);
OscilaAmort(2, .15, PI / 20, 4 * PI, LIGHTRED);
setviewport(200,
250, 400, 450,1);// Ahora esta región trabaja con la escala anterior
setbkcolor(7);
setcolor(LIGHTRED);
line(0, 0, 10,
0);
OscilaAmort(2.5, .5, PI / 20, 4 * PI, BLACK);
//
destruye la region. La escala persiste pero en toda la ventana de gráficas
setviewport();
setcolor(10);
line(0, 1, 10, -1);
escala();
// destruye la escala. Ahora todo permanece como empezamos
setcolor(11);
line(0, getmaxy(), getmaxx(), 0);
return 0;
}
void OscilaAmort(float w, float k, float dx, float xmax, int color)
{
float x =
0, y;
setcolor(color);
y = cos(w
* x) * exp(-k * x);
moveto(x,
y); // nos movemos al punto de inicio
sin trazar nada
for(x = dx; x <= xmax;x += dx)
{
y = cos(w * x) * exp(-k * x);
lineto(x, y); //
ahora juntamos segmentos de línea
}
}
Los
resultados que proporciona este programa se muestran en la figura 4.
Figura 4. Diferentes regiones para graficar la
función oscilatoria amortiguada
Como se ilustró en el primer
ejemplo, la impresión de texto en la ventana de graficas se realiza invocando a
la función outtextxy. Además de esta funcion, el intérprete cuenta dos
funciones para justificar y dar formato al texto. Estas funciones son settextjustify y settextstyle . La
primera permite alinear el texto horizontal y verticalmente de acuerdo con los
valores 0, 1 y 2 que se proporcionan mediante dos argumentos de tipo entero. El
prototipo de esta función es:
void settextjustify (int horiz, int vert);
La tabla 3 muestra las alineaciones de texto
obtenidas con la función settextjustify.
Variable |
Valor |
Resultado |
Horiz |
0 |
Alinea
horizontalmente a la izquierda |
Horiz |
1 |
Alinea
horizontalmente al centro |
Horiz |
2 |
Alinea horizontalmente
a la derecha |
Vert |
0 |
Alinea
verticalmente hacia abajo |
Vert |
1 |
Alinea
verticalmente al centro |
Vert |
2 |
Alinea
verticalmente hacia arriba |
Tabla 3. Alineaciones de texto obtenidas con la
función settextjustify
Nota: Las alineaciones
mencionadas se efectúan respecto de la posición especificada mediante la
función outtextxy
La función settextstyle
texto proporciona dirección y tamaño al texto y tiene el siguiente prototipo:
settextstyle (int font, int direccion,
double dimensión);
El
primer argumento se ignora en la presente versión del intérprete. Para colocar
texto horizontalmente, el segundo parámetro debe valer 0, y 1 si se desea una
dirección vertical. Las constantes HORIZ_DIR y VERT_DIR, integradas al
intérprete, tienen asignadas los valores anteriores. El tercer argumento
representa el tamaño del texto. Un valor de 1 corresponde a un tamaño normal
del texto. El siguiente ejemplo muestra el uso de las funciones mencionadas.
main()
{
setbkcolor(LIGHTGRAY);
cleardevice();
setcolor(LIGHTRED);
rectangle(10, 10, getmaxx() -10,
getmaxy() - 10);
setcolor(LIGHTBLUE); // texto color azul intenso
settextstyle (0, HORIZ_DIR, 5.7); //
texto horizontal y tamaño grande
settextjustify (1, 1); //
texto centrado
outtextxy(getmaxx() / 2, getmaxy() / 2, "¡Hola mundo
cruel!");
}
La
salida que produce el anterior programa se muestra en la figura 5.
Figura 5.
Impresión de texto en la ventana
de gráficas