TEMA 2.6
TRAZADO DE FIGURAS GRÁFICAS





2.6.1 - EL CURSOR GRÁFICO

Hay varias instrucciones específicas que nos permiten dibujar en la pantalla en modo gráfico. Antes de empezar a estudiar su utilización es importante darse cuenta de que en la pantalla en modo gráfico existe, además del cursor de texto, un cursor gráfico. Este sería comparable a "la punta de un lápiz que va dibujando cosas".

Al iniciar uno de los modos gráficos con la instrucción SCREEN el cursor gráfico, siempre invisible, se sitúa en el centro de la pantalla, y posteriormente, conforme vayamos dibujando cosas con las instrucciones que vamos a ver a continuación, se irá moviendo para situarse siempre al final de la última figura que hayamos dibujado. Algo parecido a lo que ocurría con el texto, pero que es conveniente aclarar.





2.6.2 - PUNTOS. INSTRUCCIÓN PSET

La primera instrucción que vamos a ver en modo gráfico nos va a permitir dibujar un punto en la pantalla en la posición que nosotros indiquemos, y del color que nosotros queramos. Su sintaxis es:

PSET (h,v),color

Los valores de h y v, siempre entre paréntesis y separados por una coma son las coordenadas horizontales y verticales del lugar en en el que vamos a dibujar el punto. Recordemos que la esquina superior izquierda de la pantalla tiene las coordenadas 0,0 y las de la esquina inferior derecha dependen del modo de pantalla elegido, en el modo 12 serán (639,479) y en el modo 13 serán (319,199).
Observa que no son (640,480) o (320,200) porque, a diferencia de las coordenadas de texto, empezamos por cero y no por uno.

Si nos salimos de la pantalla especificando coordenadas mayores o menores de los límites permitidos, no ocurre nada, simplemente que el punto se dibujará fuera de la pantalla y no lo veremos.

El valor que elijamos para el color depende de la paleta asociada al modo de pantalla que tengamos activo: Si es el modo 12 podremos usar un valor entre 0 y 15 o si es el modo 13 tendremos disponibles los valores desde 0 a 255. Evidentemente, si dibujamos un punto negro sobre fondo negro no se verá. Si no especificamos un color se usará el de la anterior orden de dibujo, si era la primera orden se usará el color blanco.

En la anterior sintaxis poníamos unas coordenadas absolutas, es decir, el cursor gráfico se movía hasta la posición indicada y se dibujaba el punto. También es posible indicar una posición relativa a la posición actual del cursor gráfico usando la palabra STEP antes del paréntesis de las coordenadas:

PSET STEP(0,0), 14

Esta instrucción dibujará un punto amarillo en la posición actual del cursor gráfico, es decir, al final de la última figura dibujada o en el centro de la pantalla si es la primera instrucción de dibujo. Vamos con unos cuantos ejemplos más de esto de las posiciones relativas:

SCREEN 13
PSET (200,100), 10
PSET STEP(0,40), 14
PSET STEP(60,0), 12
PSET STEP(-20,-20), 9

Este trozo de código activará el modo 13 y dibujará un punto verde exactamente en la posición (200,100), es decir, 200 pixels a la derecha y 100 pixels más abajo de la esquina superior izquierda de la pantalla. Seguidamente se dibujará un punto amarillo 40 pixels más abajo del anterior, uno rojo 60 pixels a la derecha del amarillo, y finalmente uno azul 20 pixels más arriba y 20 pixels a la izquierda del rojo. Como se puede ver, al usar coordenadas relativas, ya es útil usar valores negativos.

Por supuesto, los valores de las coordenadas y de los colores no tienen porqué ser expresiones constantes, pueden ser el resultado de una expresión matemática con o sin variables, por ejemplo...

PSET (inicio+largo, inicio+alto), colorActual

O algo muy útil y muy normal es que las instrucciones de dibujo están dentro de bucles que las repitan. Normalmente no nos sirve de nada dibujar un punto solo, siempre dibujaremos muchos desde dentro de bucles, por ejemplo:

SCREEN 12
FOR n=100 to 500 STEP 5
	PSET (n,50),14
NEXT

Esta instrucción dibuja en la pantalla una sucesión de puntos amarillos alineados. Si nos salimos no pasa nada, simplemente que se dibujarán fuera y no los veremos, pero si indicamos un color de fuera de la paleta del modo de pantalla actual se producirá un error de tiempo de ejecución y el programa se parará.





2.6.3 - LÍNEAS Y RECTÁNGULOS.
INSTRUCCIÓN LINE

La siguiente instrucción que vamos a ver nos va a permitir dibujar una línea recta en la pantalla. Su sintaxis es...

LINE (h1,v1)-(h2,v2),color

Aquí debemos especificar dos coordenadas: la del principio de la línea recta y la de su final. Tras dibujar la línea el cursor gráfico permanecerá en el final, es decir, en la posición de pantalla (h2,v2).
Igual que en el caso anterior, podemos especificar coordenadas relativas usando la palabra STEP antes del paréntesis para una o las dos posiciones. Esto es útil para dibujar líneas poligonales, en este caso cada segmento se dibujaría con una instrucción LINE y todas menos la primera empezarían con LINE STEP(0,0) para que empiecen junto al final de la anterior, por ejemplo este código dibuja un triángulo:

LINE (150,100)-(100,200),10
LINE STEP(0,0)-(200,200)
LINE STEP(0,0)-(150,100)

Si la última coordenada de la última instrucción es igual a la primera coordenada de la primera instrucción, tendremos una línea poligonal cerrada, en caso contrario quedará abierta.

Si la línea que estamos dibujando es completamente horizontal o completamente vertical será dibujada toda continua, si es diagonal aparecerá formando como "Escalones". Este efecto es lo que se conoce como "pixelado" y será más visible en el modo 13 ya que al ser de menos resolución, los pixels son "más gordos".

Esta instrucción LINE también nos permite dibujar un rectángulo (o un cuadrado) de forma muy sencilla, simplemente añadiendo una coma y una letra B a continuación del color, por ejemplo...

LINE (20, 20)-(70, 30), 12

Dibujaría una línea recta diagonal que va desde (20,20) hasta (70,70). Y...

LINE (20,20)-(70,30), 12, B

dibujaría un rectángulo con una de sus esquinas en la posición (20,20) y la opuesta en la posición (70,70). El borde del rectángulo tendrá una anchura de un pixel y en este caso será de color amarillo.

Si queremos que el rectángulo se dibuje relleno basta con poner las letras BF (Borde y fondo) en vez de la B sola, por ejemplo...

LINE (20,20)-(70,30), 12, BF

Si no queremos especificar el color, para que se coja el usado en la instrucción anterior, basta con no ponerlo, quedarán dos comas juntas.

LINE (20,20)-(70,30), , BF

Un poco extraño, pero cuidado con equivocarse, porque si ponemos...

LINE (20,20)-(70,30), BF

Se dibujará una línea recta entre las dos posiciones, y será del color que se almacene en una nueva variable llamada BF que seguramente será el cero que es negro y puede que no veamos. Como norma general es mejor poner el color siempre.

Al usar la segunda coordenada relativa en los recuadros, sean rellenos o no, podemos calcular fácilmente su tamaño exacto sin tener que hacer cálculos, por ejemplo:

LINE (20,20)-STEP(99,99), 14, BF

Nos dibujaría un cuadrado amarillo relleno de 100 por 100 píxeles (99 + 1) con la esquina superior izquierda en la posición que indicamos en la primera coordenada sin tener que calcular nosotros donde iría la otra esquina.
Hay que tener en cuenta que en el modo de pantalla 13 los cuadrados siempre los vamos a ver un poco más altos que anchos aunque hayamos puesto las longitudes de sus lados iguales, ya que la resolución de este modo de pantalla (320x200 píxels) no es proporcional a las dimensiones físicas del monitor que siempre guardan una proporción de 3:4. Para dibujar un cuadrado que se vea cuadrado de verdad habría que dibujarlo con una altura un poco menor que su anchura para que se disimule el error, pero tampoco no merece mucho la pena complicarse tanto en la mayoría de los casos.

Por último, podemos conseguir que las líneas y los cuadros sin relleno (B) se dibujen de forma discontinua, es decir, unos puntos sí y otros no. Para hacer esto se pone al final del todo un numerito que nos indica el patrón de puntos a utilizar. Este valor es un número de 16 bits (entre 0 y 65.535) que lo podemos poner en hexadecimal para no liarnos comenzándolo con los caracteres &H. (entre &H0000 y &HFFFF) Vamos con unos ejemplos:

LINE (20,20)-(70,30), 14,B ,&H5555

Se dibujaría un rectángulo amarillo con el borde punteado, si no queremos poner el color haríamos:

LINE (20,20)-(70,30), ,B ,&H5555

Y si queremos que sea una línea y no un rectángulo no tendríamos que poner la letra B, pero sí su correspondiente coma, sería así:

LINE (20,20)-(70,30), , ,&H5555

Esto no se utiliza mucho. Si queremos otro patrón de puntos distinto basta con ir probando números. Los más útiles pueden ser &H5555 que nos van dibujando "uno sí y otro no" y &HFF00 que nos harían un efecto parecido a la línea discontinua de una carretera. Si queremos una línea a dos colores se puede hacer dibujando una normal de un color y justo encima una discontinua del otro color, por ejemplo...

LINE (100,100)-(300,200), 15
LINE (100,100)-(300,200), 12, ,&HFF00

esto nos dibujaría una línea a trozos blancos y rojos.





2.6.4 - CÍRCULOS Y ÓVALOS.
INSTRUCCIÓN CIRCLE

La siguiente instrucción nos va a servir para dibujar una circunferencia (sólo la línea del contorno) en nuestra pantalla gráfica.

CIRCLE (h, v), radio, color

En este caso se dibujará una circunferencia con el centro situado en la posición (h,v) y con el radio (medido en píxels) que indiquemos. Tras el trazado de la misma el cursor de gráficos permanecerá en el centro. Por ejemplo:

CIRCLE (100, 200), 50, 12

Dibujará una circunferencia de color rojo con el centro en la posición (100,200) y con un radio de 50 pixels. Si no especificamos el color se tomará el de la anterior instrucción de dibujo, como en los casos anteriores. También tenemos la posibilidad de usar una coordenada relativa anteponiendo la palabra STEP al paréntesis, por ejemplo...

LINE (40, 10)-(100,200),14
CIRCLE STEP(0,0),10

...dibujaría una línea recta inclinada de color amarillo y en su extremo final una circunferencia del mismo color con un radio de 10 píxels.

La instrucción CIRCLE también nos permite dibujar arcos de circunferencia, aunque esto no se usa mucho, no hay porqué dibujarla siempre entera. Para hacerlo hay que poner a continuación del color el ángulo inicial y final del arco que queremos dibujar. Los ángulos van en radianes, la circunferencia completa tiene unos 6.28 radianes (2 veces pi) y el ángulo 0 está la la derecha, el pi/2 radianes (90º) está arriba, el pi radianes (180º) está a la izquierda y el 3/2 pi radianes (270º) está abajo. De esta forma, por ejemplo, para dibujar la mitad superior de una circunferencia (desde 0 hasta pi radianes) habría que poner:

CIRCLE (100, 100), 40, 14, 0, 3.14

Y si nos queremos ahorrar el color y que lo coja de la instrucción anterior, pues no lo ponemos.

CIRCLE (100, 100), 40, , 0, 3.14

Por último, también podemos dibujar óvalos en vez de circunferencias. Para hacerlo añadimos otro parámetro más a continuación. Este parámetro será la proporción entre el radio horizontal y el vertical. Por ejemplo, si es dos, el radio vertical será del doble que el horizontal, y si es 0.5 el radio vertical será la mitad del horizontal y la circunferencia aparecerá aplastada. El radio que nosotros hayamos puesto en la instrucción será el mayor de los dos, es decir, el horizontal si este valor es menor que 1 o el vertical si nuestro valor de aspecto es mayor que uno.

En este ejemplo dibujamos sólo la mitad izquierda de una circunferencia verde aplastada que sería cuatro veces más ancha que alta si estuviera entera:

Medio ovalo verde aplastado dibujado con la instrucción CIRCLE
CONST PI = 3.14;
CIRCLE (200, 200), 160, 9, PI/2, 3*(PI/2),0.25

Si queremos dibujar el mismo óvalo entero (Algo menos rebuscado), no ponemos los valores de principio y fin del arco, pero sí tenemos que respetar sus posiciones poniendo las comas:

CIRCLE (200, 200), 160, 9, , ,0.25

El dibujo de circunferencias no nos permite rellenarlas (Eso lo haremos en el apartado siguients), así como tampoco el trazado de una línea punteada. Las últimas cosas que hemos visto de los arcos y de los óvalos ya no serán aplicables en Visual Basic. En todo caso las circunferencias se dibujan muy pixeladas, especialmente si son de pequeño tamaño.
Hay que tener en cuenta que en el modo de pantalla 13 las circunferencias no saldrán redondas, siempre un poco más altas que anchas, ya que su resolución (320x200 píxels) no es proporcional a las dimensiones físicas del monitor que siempre guardan una proporción de 3:4.





2.6.5 - RELLENAR ÁREAS.
INSTRUCCIÓN PAINT

También es posible conseguir que una parte de nuestra pantalla se rellene de un color o de un patrón. Sería algo parecido a la herramienta "Cubo de pintura" que tenemos en la mayoría de programas de dibujo como es el caso del Paint de Windows, pero con alguna diferencia.

El funcionamiento de la herramienta "Cubo de pintura" del Paint consiste en que al pulsar sobre una parte de la pantalla con esta herramienta, todos los píxels adyacentes del mismo color cambiarán al nuevo color. Se produce un efecto como que la "pintura" se va extendiendo, sólo que es muy rápido y no lo notamos.

En QBasic la instrucción que tenemos para hacer esto es la siguiente:

PAINT (h, v), colorrelleno, colorlímite

Al ejecutar esta instrucción se produciría un efecto parecido a "Echar pintura del color colorrelleno en la posición (h, v) y esta se iría extendiendo por todos los sitios hasta encontrar píxeles del color colorlímite".
Una gran diferencia con los programas de dibujo es que el color se va extendiendo hasta quedar encerrado por píxeles del colorlímite, independientemente de los otros colores que se encuentre por el camino, a los que cubrirá.

Para especificar una posición relativa también podemos usar coordenadas relativas anteponiendo la palabra STEP como en casos anteriores.

Vamos con un ejemplo que rellenaría un círculo, algo muy común:

SCREEN 12
CIRCLE (100, 100), 40, 12
PAINT (100,100), 14, 12

Lo primero que hacemos es dibujar un círculo de color rojo (12) sobre el fondo de la pantalla que es negro porque no hay nada más dibujado. A continuación echamos pintura amarilla (14) dentro del círculo y le decimos que pare cuando encuentre píxeles rojos (12), con lo que la pintura no llegará a salirse del círculo.

El color puede ser el mismo que el color límite, pero el color límite no puede ser el mismo que el color de fondo que tiene el sitio donde empezamos a pintar, ya que entonces solamente se dibujaría un punto.

Esta instrucción puede dar lugar a que la "pintura" se salga y llene toda la pantalla, vamos con un ejemplo:

SCREEN 12
CIRCLE (100, 100), 40, 12
LINE (120, 120)-STEP(50, 50), 9, B
PAINT (100, 100), 10, 12

Primero dibujamos una circunferencia roja, después un cuadrado azul encima de la circunferencia, y al rellenar desde dentro de la circunferencia observaremos como el color verde "se sale" de la circunferencia y llena toda la pantalla, borrando también el recuadro azul. Algo así sería:

Ejemplo de como se puede desbordar el color de relleno con la instrucción PAINT

Puedes observar fácilmente que el color verde se ha salido del círculo por los dos agujeros que quedan a la derecha y abajo. Estos se produjeron al dibujar el cuadrado azul, borrando algúnos píxeles rojos.

Para evitar este problema no hay más que planificar cuidadosamente el orden en que se van dibujando los distintos objetos gráficos y las posiciones exactas donde usamos la instrucción PAINT.

Por último decir que en vez de un color sólido podemos rellenar usando un patrón de relleno, en este caso habría que sustituir el color por una cadena de ocho caracteres que codificaría el estilo del patrón. Para ver más detalles consultar la ayuda en pantalla de QBasic. No profundizaremos más en el tema porque de todas formas la instrucción PAINT ya no podrá ser utilizada en Visual Basic.





2.6.6 - DIBUJAR FIGURAS COMPLEJAS.
INSTRUCCIÓN DRAW

En los apartados anteriores hemos visto como podemos dibujar figuras elementales como puntos, líneas, recuadros y circunferencias. Para dibujar figuras más complejas podemos optar entre usar una serie de instrucciones de estas o bien usar una sola de la que vamos a ver a continuación.

DRAW CadenaComando$

Esta instrucción es completamente distinta a las anteriores. En principio no aparecen coordenadas y ¿Qué es eso de CadenaComando$...? Ahora lo vamos a ver.

La instrucción DRAW lo que hace es mover el cursor de gráficos a partir de la posición actual donde se encuentre para ir dibujando lo que nosotros queramos. Y para saber lo que nosotros queremos que dibuje se utiliza esta CadenaComando$ que no es más que una expresión de cadena o una cadena de caracteres entre comillas que contiene algunos de los siguientes caracteres para que QBasic los interprete y sepa lo que tiene que dibujar.

Estos son los caracteres que hay que poner para que el cursor gráfico se mueva en las distintas direcciones y vaya dibujando como si fuera la punta de un lápiz (Up, Down, Left, Right, E,F,G,H):

Caracteres para dibujar con la instrucción DRAW

Con un ejemplo se ve más claro. Las letras pueden ser tanto mayúsculas como minúsculas. Pero se prefieren en minúsculas para dar más legibilidad.
Imaginemos que queremos dibujar una escalera con cinco escalones que sube hacia la derecha. Basta con poner...

DRAW "ururururur"

Ya está, mira que sencillo. Si hubiéramos hecho esto con instrucciones LINE habría que haber puesto 10 instrucciones! Y haberse hartado de calcular coordenadas.

Ahora vamos a ir añadiendo cosas...

Si ejecutamos esto veremos que efectivamente se dibuja la escalera, pero muy pequeñita, ya que cada escalón solo mide de alto o de ancho un pixel. Para conseguir que los trazos sean más largos en la dirección que indiquemos no hay más que poner el número de píxeles a continuación de la letra. Haciendo lo siguiente conseguiremos que cada escalón mida tres píxeles de alto y cinco de ancho:


Escalera dibujada con la instrucción DRAW
DRAW "u3r5u3r5u3r5u3r5u3r5"

Vamos con otro ejemplo más elaborado que dibuja una flecha apuntando hacia la izquierda (Empezando por la punta):

Flecha dibujada con la instrucción DRAW
DRAW "e6d3r6d6l6d3h6"

Además de esto podemos conseguir cosas como que el cursor gráfico vuelva atrás tras haber hecho un trazo, por ejemplo para dibujar esta especie de estrella haríamos:

Estrella dibujada con la instrucción DRAW
DRAW "nu6nd6nl6nr6ne6nf6ng6nh6"

Hemos puesto una N delante de cada letra, de esta forma tras dibujar cada punta de la estrella el cursor vuelve al centro antes de dibujar la siguiente.

También podemos hacer que el cursor se mueva sin dibujar, sería algo parecido a levantar el lápiz del papel y moverlo, por eso para dibujar una línea discontinua haríamos:

DRAW "r6br6r6br6r6br6r6br6r6"

Hemos puesto una letra B delante de los trazos que no queremos que se dibujen.

Con esta forma de dibujar consegumos movel el cursor a saltitos a partir de la posición de la pantalla donde terminó el trazo anterior. También podemos hacer que salte directamente a una posición de la pantalla usando la letra M seguida de las coordenadas horizontal y vertical separadas por una coma. Por ejemplo para dibujar un triángulo usando esta técnica haríamos...

DRAW "bm100,100m140,100m120,70m100,100"

Al principio llevamos el cursor hasta la posición (100,100) sin dibujar (Poniendo la B delante) para que no se dibuje una línea desde la posición actual del cursor hasta el triángulo, cosa que no queremos. Después vamos saltando a los otros dos vértices del triángulo y finalmente volvemos hasta la posición inicial para que la figura quede cerrada.
Observa que usando esta técnica ya podemos dibujar líneas diagonales que no estén necesariamente a 45 grados.

Al usar la instrucción DRAW se utiliza el color de la anterior instrucción de dibujo, o el blanco si era la primera. También podemos especificarlo nosotros usando la letra C seguida del número del color que queramos igual que en las demás instrucciones que ya hemos visto. También como novedad podemos cambiar de color todas las veces que queramos dentro de la misma secuencia de comandos, de esta forma podremos dibujar un trozo de la figura de un color y otro de otro distinto. Como ejemplo de esto vamos a dibujar un recuadro con las líneas izquierda e inferior de verde (Color 10) y las líneas derecha y superior de azul (Color 9).


Objeto con varios colores dibujado con la instrucción DRAW
DRAW "c10d40r40 c9u40l40"

También puedes observar en este ejemplo que se ha utilizado un espacio para separar un poco las "dos partes" del recuadro. Puedes utilizar todos los espacios que quieras para separar las distintas partes de un dibujo, especialmente si hay una tira de letras muy larga.

Por último vamos a ver como hacer que las figuras dibujadas con la orden DRAW puedan estar rellenas de color. Sería algo parecido a la instrucción PAINT, pero integrada en la orden DRAW.
Basta con llevar el cursor gráfico a una posición dentro de la figura (Con la letra B para que no se dibuje) y allí dentro usar la letra P seguida del color que queremos usar de relleno y del color de bordes, que tendrá que ser el que hemos utilizado para dibujar el contorno para que "la pintura no se salga".

Como ejemplo vamos a dibujar un triángulo con el borde rojo y lo de dentro blanco...


Triángulo relleno dibujado con la instrucción DRAW
DRAW "c12 bm100,100m140,100m120,70m100,100 bm110,95 p15,12"

Empezamos por el vértice inferior izquierdo en la posición (100,100) y cuando volvemos a él para cerrar la figura hacemos saltar el cursor hasta dentro sin dibujar y rellenamos. Es importante llevar el cursor hasta el sitio interior sin dibujar ya que si lo hacemos dibujando se intentará rellenar a partir de un punto ya dibujado seguramente con el color de borde y no funcionará.

La instrucción DRAW tiene todavía más posibilidades, pero como el uso de estas otras opciones es muy raro, todavía más que el de la propia DRAW, no las vamos a ver aquí. Para saber cuales son mira la ayuda en pantalla de QBasic.
Esta instrucción es útil para dibujar figuras complejas, pero lo que aprendas de ella sólo te va a servir para QBasic. En Visual Basic ya desaparece y en otros lenguajes si existe algo parecido funciona de forma totalmente distinta.













CuRSo De iNTRoDuCCióN a La PRoGRaMaCióN CoN QBaSiC
© 2004 Juan M. González