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

void circcle(double x, double y, double radio);

cleardevice

Limpia la ventana de salida de gráficas empleando el color de fondo

void clreadevice();

clearviewport

Limpia la región de graficación empleando el color de fondo

void clearviewport();

 

escala

Establece un  sistema de coordenadas lógicas. (x1,y1) es la esquina inferior izquierda. (x2,y2) es la esquina superior derecha.

 

void escala(double x1, double y1, double x2, double y2);

 

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

int getmaxx(void);

getmaxy

Regresa la máxima ordenada física de  la ventana de gráficas

int getmaxy(void);

line

Traza una línea entre los puntos (x1,y1) y (x2,y2)

void line(double x1, double y1,  double x2, double y2);

lineto

Junta segmentos de  línea entre el último punto trazado y el punto (x,y)

void lineto(double x, double y);

moveto

Se traslada sin trazar a las coordenadas x,y

void moveto(double x, double y) ;

outtextxy

Traza una cadena de caracteres a partir de las coordenadas (x,y)

void outtextxy(double x, double y, char texto[]) ;

putpixel

Traza un punto en (x,y)

void putpixel(double x, double y, int color);

 

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

void setcolor(int color);

setbkcolor

Establece el color de fondo empleado las funciones cleardevice y clearviewport

void setbkcolor(int color);

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

void settextjustify(int horiz, int vert);

 

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.

 

void setviewport(int x1, int y1, int x2, int y2, int clip);

 

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

 

 

Colores

 

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.

 

 

 

Color

Constante

Número

negro

BLACK

0

azul

BLUE

1

verde

GREEN

2

azul-claro

CYAN  

3

rojo

RED

4

morado

MAGENTA

5

café

BROWN

6

gris claro

LIGHTGRAY

7

gris obscuro

DARKGRAY

8

azul intenso

LIGHTBLUE

9

verde intenso

LIGHTGREEN

10

azul -claro intenso

LIGHTCYAN

11

rojo intenso

LIGHTRED

12

morado intenso

LIGHTMAGENTA

13

amarillo

YELLOW

14

blanco intenso

WHITE

15

 

Tabla 2. Colores disponibles para el trazo de gráficas

 

 

Primitivas

 

 

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

 

 

 

Sistema de coordenadas lógicas

 

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);

clearviewport();

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

 

 

 

Salida gráfica de textos

 

 

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