Adrianistán

¡Feliz navidad y próspero 2018! (con fractales)

22/12/2017
Feliz Navidad! Si estás leyendo esto, darte las gracias por seguir leyendo este blog. Me alegro mucho de tener cada vez más lectores y es algo que me anima a escribir más y más. En este especial navideño disfrutaremos de éxitos musicales de la navidad, veremos como hacer un fractal muy navideño en Rust y os pediré vuestra opinión.

Comenzamos con In Dulci Jubilo y este cover de Giuliano Ferrace Leanza


El fractal de Koch


Helge von Koch fue un matemático sueco que en 1904 publica un artículo sobre la que desde entonces se llamaría curva de Koch. Se trata de una curva, generada con unas reglas muy simples. La idea fundamental es que se parte de una recta, que se divide en tres trozos iguales. El trozo del medio se sustituye por un triángulo equilátero. Entonces la curva recorre el primer trozo, sube el triángulo, baja el triángulo y continúa recto.

Si ahora en cada uno de los cuatro trozos rectos aplicamos la misma curva de Koch obtenemos esto:

Según la terminología de Mandelbrot, este fractal es un teragón. Si ahora en vez de aplicar esto sobre una recta, lo hacemos sobre un triángulo equilátero con sus tres trozos rectos iguales, ¿qué obtenemos?

Turtle, una librería de Rust para gráficos tortuga


Quizá entre mis lectores haya alguno que aprendió a programar con LOGO. Una de las características de LOGO era que disponía de una tortuga con la que íbamos dibujando según nos movíamos. Esta manera de dibujar, no es óptima en rendimiento puro, pero es ideal para fractales y para enseñar a programar. Python incorpora en su librería estándar el módulo turtle y en Rust está a punto de salir una librería que soporta una API similar llamada turtle.

Lo primero que tenemos que hacer es definir la curva de Koch con turtle.
    fn koch(&mut self, length: f64){
self.forward(length/3.0);
self.left(60.0);
self.forward(length/3.0);
self.right(120.0);
self.forward(length/3.0);
self.left(60.0);
self.forward(length/3.0);
}

Con esto nos valdría, pero no es recursivo. Necesitamos poder aplicar la curva de Koch en nuestras rectas (donde hacemos forward) de forma recursiva. Pero si lo hacemos recursivo de forma infinita no acabará nunca, es por ello que tenemos que indicar cuantos niveles de recursividad queremos.
    fn op(&mut self, length: f64, level: u32) {
if level == 0{
self.forward(length);
}else{
self.koch(length,level);
}
}
fn koch(&mut self, length: f64, level: u32){
self.op(length/3.0,level-1);
self.left(60.0);
self.op(length/3.0,level-1);
self.right(120.0);
self.op(length/3.0,level-1);
self.left(60.0);
self.op(length/3.0,level-1);
}

Esto ya tiene más sentido. Ahora juntemos todo lo necesario:
extern crate turtle;

use turtle::Turtle;
use turtle::Distance;

trait Fractal{
fn koch(&mut self, length: f64, level: u32);
fn op(&mut self, length: f64, level: u32) {
if level == 0{
self.forward(length);
}else{
self.koch(length,level);
}
}
fn forward(&mut self, distance: Distance);
}

impl Fractal for Turtle{
fn koch(&mut self, length: f64, level: u32){
self.op(length/3.0,level-1);
self.left(60.0);
self.op(length/3.0,level-1);
self.right(120.0);
self.op(length/3.0,level-1);
self.left(60.0);
self.op(length/3.0,level-1);
}
fn forward(&mut self, distance: Distance){
self.forward(distance);
}
}

fn main() {
let mut turtle = Turtle::new ();
turtle.set_pen_size(2.0);
turtle.pen_up();
turtle.go_to([-200.0,100.0]);
turtle.pen_down();
turtle.set_speed(0);
turtle.hide();
turtle.right(90.0);
turtle.koch(400.0,5);
turtle.right(120.0);
turtle.koch(400.0,5);
turtle.right(120.0);
turtle.koch(400.0,5);
}

Si compilamos y ejecutamos esto con Cargo:

Y aquí tenemos al copo de nieve de Koch.

Tenéis el proyecto completo en GitHub: https://github.com/aarroyoc/fractal_koch_rust

Fractal (bis)


Otro fractal muy interesante que programé mientras estaba haciendo el copo de nieve fue este otro. Desconozco si tiene nombre. Es algo más complejo de implementar y lo de los colores me dio bastantes dolores de cabeza hasta que encontré una progresión bella.

Su código es (en este caso Python):
from turtle import *
from math import cos, pi

a = 0

def fractal(length=100,level=1,flip=False):
# 3906 llamadas a fractal = 5^5 + 5^4 + 5^3 + 5^2 + 5^1 + 5^0
((r,g,b),_) = color()
global a
a += 1
if a % 7 == 0 and a < 1953:
b += 1
if a % 7 == 0 and a > 1953:
r += 1
b -= 1

r = min(r,255)
g = max(g,0)
b = min(b,255)
b = max(b,0)

color(int(r),int(g),int(b))

if not flip:
left(90)
else:
right(90)
if level == 1:
forward(length)
else:
fractal(length*length/(2*cos(45)*length/2+length),level-1,flip)
if not flip:
right(45)
else:
left(45)
if level == 1:
forward(length/2)
else:
fractal(length*length/(4*cos(45)*length/2+length),level-1,not flip)
if not flip:
right(45)
else:
left(45)
if level == 1:
forward(length)
else:
fractal(length*length/(2*cos(45)*length/2+length),level-1,flip)
if not flip:
right(45)
else:
left(45)
if level == 1:
forward(length/2)
else:
fractal(length*length/(4*cos(45)*length/2+length),level-1,not flip)
if not flip:
right(45)
else:
left(45)
if level == 1:
forward(length)
else:
fractal(length*length/(2*cos(45)*length/2+length),level-1,flip)
if not flip:
left(90)
else:
right(90)

def main():
colormode(255)
penup()
pensize(2.0)
setx(-100)
sety(-200)
pendown()
color(0,255,0)
speed(0)
tracer(False)
fractal(50,6)
done()


main()

 


Vuestra opinión


Ahora os pido que me déis vuestra opinión sobre el blog. Usad los comentarios de debajo y contadme: ¿Cuál es el mayor problema del blog?, ¿crees que los contenidos salen con frecuencia suficiente y necesaria?, ¿los temas son interesantes?, ¿me voy mucho por las ramas?, ... Todo esto lo tendré en cuenta de cara al año que viene.

Aprovecho para recordar que podéis suscribiros a la lista de correo para que os llegue un nuevo correo con cada post, podeís suscribiros al blog por RSS, hay un canal de Telegram y una página en Facebook. En Twitter, GNU Social e Instagram solo tengo perfiles personales, pero si os interesa, allí estoy. Por último en Google+ todavía sigo mandando los artículos.

Si os parece que me merezco una caña, siempre puedes donar usando PayPal, criptodivisas, tu apartamento en Comillas, ...

Sin más, feliz próspero año 2018



 
Tags: fractal turtle feliz-ano programacion koch 2018 2017 linux rust tutorial navidad python