Una máscara africana, dibujada con una tortuga
Estudio de código · 2018
El código más antiguo que conservo. Tenía once años y había dado con la forma de dibujar una curva usando solo líneas rectas, que resulta ser la idea con la que los ordenadores dibujan curvas.
Qué es
En abril de 2018 subí un fichero llamado turtle-afrincan-mask.sb —«African» mal escrito, y he dejado la errata donde estaba— a mi primer repositorio de GitHub. Tenía once años.
Dibuja una máscara en Microsoft Small Basic con la Tortuga: un cursor que se maneja con Move y Turn, la misma idea que Logo. Sabe avanzar y sabe girar. No sabe lo que es un círculo.
Lo pongo aquí porque volví a leerlo hace poco y encontré algo que no esperaba: la Carla de entonces ya había dado con la idea correcta.
La única idea
Todas las curvas del dibujo están hechas de líneas rectas. La cara, los ojos y la barbilla salen todos de esto:
sides = 50
length = 400 / sides
angle = 90 / sides
For j = 1 To sides
Turtle.Move(length)
Turtle.Turn(angle)
EndFor
Avanzar un poco, girar un poco, cincuenta veces. Cada paso es recto; el giro acumulado curva el recorrido.
Lo que hoy defendería es la división. Tanto la longitud como el ángulo se dividen entre sides, así que la distancia total recorrida siempre es 400 y el giro total siempre es 90°, valga lo que valga sides. El arco no cambia de forma. sides solo controla con qué finura se dibuja.
Eso lo convierte en un mando de resolución, y un solo número cambia a la vez todas las curvas del dibujo:
Con sides = 3 el truco queda al descubierto: la «curva» son tres rectas. Con 50 el ojo ya no encuentra las esquinas.
El radio sale de los dos parámetros. Para un paso de longitud y un giro por paso, el polígono resultante queda inscrito en una circunferencia de radio
Con y , eso da un radio de unas 255 unidades, y por eso la cara ocupa la ventana como la ocupa. A los once no conocía esa fórmula. Llegué ahí probando números hasta que quedaba bien, que es una manera perfectamente legítima de dar con una curva.
Esto es, más o menos, lo que hace una tarjeta gráfica: las curvas se aplanan en segmentos y la única pregunta real es cuántos.
Qué más hay dentro
Hay dos cosas que me alegra haber hecho.
Reiniciar el rumbo. La geometría de tortuga es relativa: cada giro se mide a partir de la orientación que tenga la tortuga en ese momento. Para colocar un elemento en una posición absoluta hay que normalizar antes, y el fichero hace justo eso:
Turtle.PenUp()
Turtle.MoveTo(300,200)
Turtle.PenDown()
Turtle.Turn(-Turtle.Angle)
Turn(-Turtle.Angle) gira el opuesto del rumbo actual, lo que lo deja a cero. Es el equivalente en tortuga a reiniciar un sistema de referencia, y equivocarse ahí es la razón habitual de que un dibujo de tortuga salga girado.
Separar el estado del lápiz de la posición. PenUp, mover, PenDown: desplazarse sin dibujar. Evidente cuando ya lo sabes, nada evidente cuando lo estás descubriendo.
Qué está mal
Ser honesta con el código es más interesante que defenderlo.
Los comentarios describen otro programa. Un bloque lleva el comentario ' Left eye y el siguiente ' Right eye. Y no lo son. El primero dibuja el anillo interior de los dos ojos, en x = 250 y x = 350; el segundo dibuja el exterior de ambos, en x = 240 y x = 360. Organicé el código por anillos y los comentarios por ojos.
Tres de los cuatro círculos no reinician el rumbo. El primer ojo hace Turn(-Turtle.Angle); los otros tres solo hacen TurnRight() en la dirección en que los haya dejado MoveTo. Un arco de 360° se cierra sobre sí mismo de todas formas, así que el fallo no se ve en el resultado, pero es suerte y no diseño, y por eso los anillos quedan algo descentrados respecto al punto desde el que se trazaron.
Todo son números mágicos. 300, 400, 250, 150, 60, 100. Nada se deriva de nada, así que mover la cara significa editar once coordenadas a mano. El parámetro sides muestra que el instinto de abstraer ya estaba ahí; solo que aún no había llegado a la geometría.
Por qué lo conservo
Ahora escribo pipelines de análisis donde el objetivo es exactamente que un parámetro se declare una vez y todo lo demás se derive de él. Es el mismo instinto que dividir entre sides, solo que ahora tengo mejores palabras para nombrarlo.
Y tiene la forma de todo lo que me ha gustado en ingeniería desde entonces: algo continuo aproximado por algo discreto, con un mando explícito que controla cuánto error estás dispuesta a aceptar.
El repositorio está igual que en 2018 salvo por su README. La reimplementación en Python que genera las figuras de esta página está en el repo, así que el dibujo se puede ejecutar sin instalar Small Basic.