Espirògraf

De Viquipèdia
Salta a la navegació Salta a la cerca

L'espirògraf és una joguina de dibuix geomètric que permet traçar corbes matemàtiques estil ruleta, tècnicament conegudes com a hipotrocoide i epitrocoide. Va ser desenvolupat per l'enginyer britànic Denys Fisher i venut per primera vegada el 1965.

En computació, la idea es pot ampliar de forma recursiva per generar un espirògraf fractal, on el cercle generatiu actua a la vegada de cercle directiu d'un de més petit, i així successivament generant cada vegada més detall en el traç final d'una manera similar a les sèries de Fourier complexes. Dit d'una altra manera, un espirògraf bàsic de dos cercles (l'immòbil, anomenat directiu, i el que fa la rotació, anomenat generatiu) es pot considerar el cas més simple d'una família de corbes trocoides.

Base matemàtica[modifica]

Es necessiten definir varis de paràmetres per construir un espirògraf; el nombre total de cercles directius (n), la ratio entre els radis dels diferents cercles (m), la ratio entre la velocitat de gir dels diferents cercles (k), i la distància de cada cercle (d) respecte el centre de l'anterior.

El radi del cercle actual es calcula utilitzant la ratio descrita, .

La distància del cercle actual respecte el centre es calcula tenint en compte el radi del cercle anterior i el del cercle actual, , aplicant la suma en el cas de l'epitrocoide i la resta en el de l'hipotrocoide.

La velocitat de gir es calcula partint de la velocitat de gir del cercle anterior i aplicant una ratio constant. Aquesta ratio és gairebé sempre negativa, és a dir, la direcció de rotació va alternant-se a cada cercle.

La fórmula més bàsica seria . Aquesta velocitat és la que s'utilitza per actualitzar l'angle .

Obtenim la posició de cada cercle:

Aquesta posició de l'últim cercle serà la utilitzada per aplicar el traçat final de l'espirògraf.

Exemple en pseudocodi:

// Definir els paràmetres necessaris
n = 11
r_ratio = 3
d_prev = 0.5
d_current = 0.5
k = -4

// Crear el cercle inicial
ary orbits = []
circle = Circle.new(size) // Mida del cercle immòbil
// Emmagatzemar tota la informació necessària del cercle
orbit = Orbit.new(circle, d=0, angle=0, speed=1)
orbits.push(o)

// Crear cadascun dels cercles partint de l'anterior
for i in 1...n
  prev = orbits[i - 1]
  size = previous.circle.size / r_ratio
  circle = Circle.new(size)
  circle.x = prev.circle.x
  circle.y = prev.circle.y
  d = previous.ciecle.size * d_prev + circle.size * d_current
  angle = previous.angle
  speed = previous.speed * k
  orbit = Orbit.new(circle, d, angle, speed)
  orbits.push(orbit)
end

// Actualitzar el dibuix canviant l'angle constantment
loop do
  // Actualitzar la posició de cada cercle
  Graphics.update
  for i in 1...orbits.size
    prev = orbits[i - 1]
    orbit = orbits[i]
    orbit.angle += orbit.speed
    d = orbit.distance
    dx = prev.circle.x + d * Math.sin(angle)
    dy = prev.circle.y + d * Math.cos(angle)
  end
  // Traçar el dibuix
  last = orbits[-1].circle
  if (last_drawn != NULL)
    sx = last_drawn.x
    sy = last_drawn.y
    draw_line(sx, sy, last.x, last.y)
  else
    set_pixel(last.x, last.y)
  end
  last_drawn = Point.new(last.x, last.y)
end

Enllaços externs[modifica]