Dibujando polígonos con Python y Turtle
En el presente artículo propongo hacer uso del modulo “Turtle” de python, el cual constituye una interesante herramienta para crear nuestros propios gráficos con python. En este caso concreto nos proponemos a crear un sencillo programa que, a partir de ciertos datos que nosotros le proporcionaremos, nos dibujará cualquier polígono que nosotros le pidamos. He aquí un ejemplo de ejecución del programa que vamos a crear:
En la imagen se muestran, simultáneamente, los inputs introducidos (en el lado izquierdo), y el polígono finalmente generado por el programa (en el lado derecho). Como se puede ver, nuestro programa nos da la opción de seleccionar aspectos tales como el color del fondo y del polígono (los cuales habrán de introducirse en inglés), las coordenadas del punto a partir del cual se dibujará nuestro polígono, el grosos de la línea, el número de lados del polígono y la longitud de cada uno de los lados.
Lo primero que debemos hacer, como suele ser, es importar aquellos módulos que contienen aquellas funciones que vamos a utilizar para crear nuestro programa.
Como se aprecia en la imagen, hemos importado el modulo “turtle”, el cual contiene las herramientas, funciones y recursos gráficos que vamos a necesitar para dibujar nuestro polígono. Junto a esta, también importamos “subprocess” y el módulo “VALID” (del que hablo en este articulo: https://www.pythondiario.com/2018/01/creando-calculadoras-del-tiempo-2-el.html ) del que importaremos las funciones “OKI”, “OK”, “ns”. Los que no tengan ese modulo (“VALID”) tendrán que escribir las siguientes funciones:
Una vez que hemos importado aquello que necesitamos para hacer funcionar nuestro programa, ya podemos empezar con el desarrollo de nuestro programa.
Lo primero que vamos a preguntarle a nuestro usuario, es si desea “activar” la ventana en la que vamos a dibujar nuestro polígono:
De modo que en el caso de que la respuesta sea afirmativa (lo que indicaremos escribiendo “s”, tal y como nos lo pide la función “ns”), se creará una ventana mediante el comando “t=Turtle ()” (hay que decir que donde yo he puesto “t” se podría haber puesto cualquier cosa ya que la única función de esa variable es la de definir nuestra ventana), como la que se ve en la imagen. Es en dicha ventana, donde se irán dibujando las figuras (en este caso, polígonos) que vamos a definir mediante una serie de parámetros (longitud del lado, ubicación, color, grosor de línea, y número de lados). Por otra parte, nuestra figura (por defecto) va a ser dibujada por un puntero que aparecerá en pantalla (como se ve en la imagen de abajo, a la izquierda). Este puntero lo podemos “ocultar” mediante el comando “t.hideturtle ()” (tal y como se ve en la imagen de abajo, a la derecha).
Una vez hecho esto, es hora de introducir las variables que determinarán las características de nuestro dibujo. Para empezar, vamos a dar al usuario, la posibilidad de seleccionar el color del fondo sobre el que se creará nuestro polígono.
Aquí, hemos creado una variable (al que hemos denominado “cf”) la cual almacenara el color que queremos para el fondo de la imagen. Como es natural, en este caso no nos vale con cualquier input, sino que ha de ser una palabra que python reconozca como color (como por ejemplo: “red”,”blue”...etc). Para ello hemos creado una función a la que hemos llamado “set_color”, la cual aplicamos sobre nuestro input, y se va a encargar de “asegurarse” de que el input introducido sea válido (reconocible) para python. Como es natural dicha función la habremos definido con anterioridad y será la siguiente:
Esta función toma como argumento el input introducido, para a continuación “intentar” (con “try”) establecer el color de fondo de nuestra ventana “t”, mediante la función “screen.bgcolor()”. De modo que en el caso de no poder llevarse a cabo ese establecimiento del color para el fondo (por tratarse de una palabra no reconocible para tal función), se producirá una excepción (mediante “except”), la cual nos dará un mensaje (“Color no valido: “) con el que darán nuevamente, al usuario, la posibilidad de introducir el input correctamente. Una vez terminado este proceso de comprobación de validez de nuestro input, mediante “return”, la función establecerá el color de nuestro fondo.
Una vez seleccionado el color del fondo, haremos algo muy parecido para escoger el color que tendrá nuestro futuro polígono, para ello crearemos la correspondiente variable (que llevará el nombre de “ct”). Así escribiremos:
Para asegurarnos de que el usuario introduce un nombre de color válido, como hicimos para el color del fondo, crearemos una función (“set_color2”), que nuevamente intentará tal operación, dándonos la oportunidad de introducir un color valido, en caso de que no se haya podido realizar la operación y establecerá el color del contorno en el caso de que el input introducido sea el adecuado.
Con las variables “cf” y “ct” y sus correspondientes funciones (“set_color” y “set_color2”), tenemos, ya, establecidos los colores del fondo y el contorno del polígono que vamos a crear. Pero en este punto, debemos recordar que lo que queremos es que sobre el fondo de nuestra ventana, se dibuje un polígono que se pueda distinguir sobre tal fondo. Para ello será necesario que el color del fondo y del contorno no sea el mismo. Para asegurarnos de ello utilizaremos un ciclo “while” que especifique que mientras que ambos colores coincidan (“cf” y “ct”) aparezca un mensaje instándonos a introducir un color para el contorno que sea distinto del fondo:
El siguiente dato que el usuario tendrá que proporcionar a nuestro programa, es el grosor que va a tener la línea del contorno de nuestro polígono. Para ello crearemos una variable (a la nombraremos como “gt”) la cual almacenará un numero que podrá tener decimales (motivo por el cual usaremos, también, la función “OK”, la cual, creamos en su momento para asegurarnos de que el input introducido por el usuario es, efectivamente un número). Este número definirá (haciendo uso de la función “.pensize()”) el grosor de la línea del contorno (de modo que cuanto mayor sea dicho número, más gruesa será la línea que dibuje nuestro polígono).
Establecido el grosor de la línea que definirá el contorno, lo siguiente que haremos será definir que polígono (triangulo, cuadrado, pentágono…etc) es el que queremos dibujar. Esto lo estableceremos mediante dos variables (el número de lados “n” y la longitud de cada lado “ln”): Así, en primer lugar, pediremos al usuario que introduzca el número de lados que va a tener el polígono. Esta información la almacenaremos en la variable “n”, sobre la que aplicaremos la función “OKI” (la cual “obliga” al usuario a introducir solo números enteros). Y en segundo lugar, pidiendo la longitud que tendrá cada lado (que no es otra cosa que la longitud de cada trazo):
Pero ¿Cómo conseguimos que python dibuje nuestro polígono a partir de estos dos datos? Para ello usaremos las funciones “.left()” y “.fd()” dentro de un ciclo “for”. Para entender mejor como funcionan (y para qué sirven) esas dos funciones, pondremos un sencillo ejemplo:
Como se puede ver, hemos creado nuestra “área de dibujo” escribiendo “t=Turtle()”, acto seguido, hemos especificado un grosor de línea de 45 (“con t.pensize(45)”). Luego hemos dado la orden al puntero (que inicialmente apunta hacia la derecha) de que gire 60 grados (en relación a la horizontal) hacia la izquierda (“t.left(60)”). Finalmente hemos dado la orden (escribiendo “t.fd(178)”) de que el puntero trace una línea recta, cuya longitud viene especificada por el número entre paréntesis (178). En cuanto al color del fondo y de la línea, no hemos especificado nada en este caso, por lo que nos han salido los colores que están por defecto (blanco para el fondo y negro para la línea).
Pues este es el procedimiento que vamos a emplear para la creación de nuestro polígono:
Donde “n” es el número de lados de nuestro polígono (el cual ya especificamos en su momento), “ln” es la longitud de cada trazo (que también hemos especificado) y “ang” número de grados que tendrá que girar el puntero hacia la izquierda en cada ejecución del ciclo (que también habremos calculado).
Como sabemos nuestra variable “ang” expresa el número de grados que girará el puntero en cada ejecución del ciclo (número que será constante). A continuación vamos a determinar ese número de grados, el cual calcularemos a partir del número de lados.
Existe en matemáticas una fórmula que relaciona el número de lados de un polígono con la amplitud de sus ángulos internos:
((n-2)/n)*180
En donde “n” es el número de lados del polígono. Esta fórmula es la que emplearemos para calcular la variable “ang”. Sin embargo hemos de tener en cuenta que nuestro polígono (al emplear la función “.left()”) construirá nuestro polígono tomando como referencia sus ángulos externos, con lo cual (y teniendo en cuenta que el giro del puntero se realiza con respecto a la horizontal) tenemos que el modo de calcular nuestra variable “ang” será:
ang=180-(((n-2)/n)*180)
De ese modo ya tenemos el modo de calcular el ángulo (en este caso, externo) de nuestro polígono. De ese modo definiremos en nuestro programa la variable “ang” (con anterioridad al ciclo “for”):
Con lo que hemos completado el modo de crear nuestro polígono. Veamos un ejemplo de ejecución del programa:
Lo que nos da el siguiente resultado en nuestra ventana Turtle:
Como se puede ver, hemos dibujado un polígono de tres lados (triangulo), el cual se ha dibujado a partir de la coordenada x=0 y=0. Esto es debido a que ante la pregunta “¿Especificar coordenadas?:” hemos dicho que no. Y es el programa que hemos creado, nos permite especificar las coordenadas a partir de las cuales queremos que se construya nuestro polígono. Lo cual hemos hecho del modo siguiente:
Así con este bloque de código (que escribiremos antes del ciclo “for”), lo que hacemos es especificar las coordenadas (a través de2 las variables “coordenada_x” y “coordenada_y”). Las cuales quedarán establecidas mediante las funciones “.setx” y “.sety”. Hay que resaltar que esta parte del programa no dibuja nuestro polígono, lo único que hace es situar el puntero en el punto que nosotros le indiquemos, para, desde dicho punto, proceder a dibujar (haciendo uso del ciclo que explicamos más arriba) nuestro polígono. De modo que el puntero se desplazará a dicho punto para dibujar el polígono. Veamos ahora un ejemplo en el que dibujamos el polígono especificando las coordenadas:
Vemos como en este caso (en el que procedemos a crear un cuadrado de contorno negro, sobre fondo verde), hemos introducido una respuesta afirmativa ante la pregunta de si deseamos especificar las coordenadas. De modo que tras especificar que queremos que se dibuje a partir de la coordenada x=34 y=90, ejecutamos y obtenemos el siguiente resultado:
Efectivamente nuestro cuadrado se ha creado a partir del punto especificado. Sin embargo no todo ha salido bien: Como puede verse, el puntero, al trasladare (en dos fases: primero en x y luego en y) al punto especificado, nos ha dibujado una delgada línea negra que no queremos que aparezca. Esto ha sido debido a que el puntero también ha dibujado en el transcurso de su trayecto una línea del color que nosotros habíamos especificado para el contorno (mediante la variable “ct”). Para que esto no suceda debemos introducir un cambio sencillo en nuestro código anterior:
Lo que hemos hecho aquí ha sido (mediante “t.color(cf)”) decir que solo para el trayecto, del puntero, del centro a la coordenada especificada, el color de la línea se haga igual al color que habíamos escogido (mediante la variable “cf”) para el fondo. De modo que, solo después de que el puntero se haya posicionado en la coordenada elegida, volveremos a darle a la línea su color original (el de la variable “ct”). Una vez introducido estos cambios, volveremos a ejecutar el programa, introduciendo los mismos datos que en la ejecución anterior, obteniendo el siguiente resultado:
Ahora sí que hemos creado nuestro cuadrado tal y como lo queríamos, y en el punto del área de dibujo que deseábamos.
Con esto ya tenemos creado nuestro programa para dibujar cualquier polígono que queramos a partir de los datos que suministremos a la computadora. Ya tan solo nos queda dar la posibilidad de volver a crear un nuevo polígono sin necesidad de reiniciar el programa. Teniendo en cuenta que la ejecución de todo el programa constituye un bucle que emplea la formula “while True:” (de modo que la ejecución se termina mediante una sentencia “break”), escribiremos:
De modo que, si ante la pregunta de si queremos continuar, el usuario da una repuesta afirmativa (con “s”), mediante “t.clear()”, se procederá a borrar el polígono que hayamos creado, dejando el área de dibujo, lista para empezar de nuevo.
El código de los programas referidos en este artículo puede verse, en mi perfil de GitHub, en la siguiente dirección: https://github.com/antonioam82/Poligonos.
Escrito por: Antonio Alfonso Martinez.
Deja una respuesta
que lindo, dibujar con la tortuga es lo mas!