Fractal - Um tutorial

Bom, como muitas das buscas no google que vem parar por aqui estão relacionadas com fractais, resolvi escrever esse pequeno tutorial sobre fractais. Eu não sou especialista no assunto, minha experiência com fractais é ligada à computação e não à matemática. Gosto de implementar programas que desenham fractais porque acho "bonitinho", mas minha base matemática é fraquinha, e não me arrisco muito na teoria por trás dos fractais.

Conteúdo

Histórico

Meus histórico com fractais é antigo. Eu tenho uma tia que é Matemática e tem suas linhas de pesquisa nessa área (na verdade em teoria do Caos, mas fractais tem tudo a ver com isso). No início eram só figurinhas bonitinhas que eu via nos livros dela. Depois comprei meu primeiro PC (antes eu tive computadores "menores" como o Apple II ou o Comodore 64) e de alguma forma, seja através da minha tia, seja por outros meios quaisquer (não me lembro mesmo) pus a mão em programinhas de fractais. E ficava encantado com aquelas cores e formas estranhas!

Então no meu primeiro ano de faculdade consegui uma iniciação científica com Teoria do Caos. Eram bilhares convexos. Na verdade, eram dois círculos um dentro do outro e uma "bolinha" virtual que batia nas paredes dos círculos e refletia (ou refratava, dependendo da forma que estivéssemos usando). A gente fazia gráficos bonitinhos com o ângulo×posição de onde a bolinha batia em cada círculo. Estudei matemática pacas, e no fim só fiz uns desenhozinhos. Mas foi legal! Aí comecei a me interessar pelo assunto.

Em 1995 quando lançaram o java eu fiz minha primeira applet: um conjunto de Mandelbrot. Com o tempo foi incrementando ele, e hoje tem até zoom, e está bem estruturado num modelo MVC e tudo mais.

Aí parei durante anos... Nem olhei mais pra isso, mas sabia bem como funcionava. Até que o Rickbit resolveu me desafiar a fazer um Mandelbrot com menos de 512 bytes. Ele ganhou, claro, mas me reentusiasmei pelos fractais. Fiz mais alguns experimentos, todos com fractais do tipo "tempo de escape". Uma listinha dos que fiz nessa época:

Mais um tempão parado, e comecei a montar esse site. Lembrei do BuddhaBrot e resolvi bincar com ele mais um pouco. Acabei fazendo um "BuddhaBrot" do "Burning Ship". Acabei colocando os links todos nesse site, e os fontes também.

Agora o google me acha em várias buscas por fractal, e eu resolvi escrever um pequeno tutorial de implementação de fractais de "tempo de escape" em funções recorrentes. Aqui vai...

Tutorial

Um fractal do tipo do mandelbrot é uma função recorrente (ou recursiva, para os computeiros de plantão) no plano complexo. Se você não entendeu nada, acho melhor estudar um pouco mais de matemática ou pular a parte da teoria. Se entendeu alguma coisa, vou detalhar melhor daqui pra frente.

Plano complexo

ou plano de Argand-Gauss é um plano cartesiano onde representamos os números complexos. Bom, pra continuar, melhor falar o que são números complexos. Alias, espero que vocês já saibam, porque minha explicação vai ser bem fuleira!

Números complexos

São uma extensão do conjunto R dos números reais, conhecido também por mathbb{C}. Eles representam os números que tem uma parcela imaginária. Aí complicou pra explicar isso. Bom, pra quem não sabe, não existe representação de raiz quadrada de número negativo. Então uns matemáticos doidões aí inventaram o tal do i. Esse i é a raiz quadrada de menos 1, assim:

i = sqrt{-1}

E com isso uma pancada de números que não existiam, passaram a existir e serem escritos assim:

c = a + bi onde a e b são constantes.

Isso aí são os números complexos, definidos matematicamente assim:

mathbb{C} = { a + bi | a in R, b in R }.

Então volto pro

Plano complexo

Que agora ficou uma moleza! É um plano cartesiano (que foi inventado por Descartes, ao contrário do poço cartesiano) normal, só que ao invés de termos o valor de x e de y de uma função pra desenhar, a gente desenha no eixo horizontal (que era o x) o valor de a e no eixo vertical (que era o y) o valor de b (a e b daquela fórmula lá de cima,lembra? c = a + bi). Ficou fácil, né? Um número complexo deixa de ser uma coisa unidimensional como um número qualquer e passa a ser uma coisa bidimensional.

Função recorrente

ou recursiva, é uma função que usa o valor dela mesma pra calcular um próximo passo. Por exemplo (um clássico) a seqüência de Fibonacci onde cada número é a soma dos seus dois anteriores (e dá algo como 1,1,2,3,5,8,13,21,...), que é definida assim:

f(n) =  begin{cases}  1               & n = 0 mbox{ ou } n = 1, \  f(n-1) + f(n-2) & n > 1. end{cases}

Ou as vezes escrito também assim: f(0) = 1, f(1) = 1, f(n) = f(n ? 1) + f(n ? 2) para n > 1

Bom, qualquer função f que faça referência a ela mesma (ou seja, que tenha f(...) do lado direito da fórmula) é uma função recorrente. Os fractais que vamos ver são funções desse tipo, mas bem especiais. A função de Fibonacci que mostramos, se aplica a números inteiros, certo? Existem algumas que se aplicam também a números reais (f(n) = f(n ? 1) * ? por exemplo). Os nosso fractais se aplicam a números complexos! Nada de mais. É só que calcular somas e multiplicações de números complexos é um pouquinho mais chato que calcular as mesmas somas e multiplicações com números "normais". Estou com preguiça de ensinar como faz isso aqui, então dê uma procurada no google se você não souber!

E passada a introdução, podemos finalmente nos concentrar nos...

Fractais

Finalmente. Vamos começar pelo mais simples. O mais simples é o Conjunto de Mandelbrot. Não sei se é o mais simples mesmo não, mas é o mais famoso! Isso já basta. A gente começa com uma função, que o tal do Benoit Mandelbrot descobriu nos idos da década de 70 ou 80. Ela é assim:

Z_{n+1} = Z_{n}^{2} + C, Z_{0} = 0, onde C e Z são complexos.

Ele descobriu também que se algum dia |Z_{n}| (que é calculado como sqrt{a^2 + b^2}) passar de 2, a função vai com certeza virar infinito mais cedo ou mais tarde. Esse caso (quando a função vira infinito) a gente diz que ela diverge ou que ela escapa (Entendeu porque o tempo de escape? Porque a função escapa... duh!).

Aí ele resolveu brincar com essa função. O lance todo é que pra brincar, ele desenhou no plano complexo todos os valores possíveis pra C. Pra cada ponto ele contou quantas vezes precisava aplicar a função ali em cima pra que o valor "escapasse". O "tempo" de escape é o número de vezes que eu aplico a função antes que ela escape. Aí ele escolheu uma cor diferente pra cada tempo de escape, e coloriu cada ponto C no plano complexo com a cor correspondente ao tempo que levou pra escapar. O resultado é uma figurinha bacaninha que nem essa daqui ó:

imagem:mandelbrot_simple.png

Ficou fácil de entender? Então vamos fazer isso no computador!

Implementação

Implementar isso parece simples. E é simples pra caramba! Olha só:

  1. você escolhe uma função f(n) (no caso do Mandelbrot f(n) = f(n ? 1)2 + C)
  2. você escolhe um pedaço do plano complexo pra desenhar (na figura ali de cima a gente usa a parte real de ? 2,0 a 1,0 e o imaginário de ? 1,57i a 1,43i)
  3. você calcula a escala da sua tela em relação ao intervalo escolhido ali em cima (no meu caso foi tfrac{1}{100})
  4. você itera cada ponto da tela até ele escapar ou atingir um número máximo de iterações (eu usei 40, pra ficar rapidim mesmo).
  5. aí pinta o ponto de acordo com o "tempo" de escape, ou pinta de preto quando ultrapassar o número de iterações.

Manha né?

O exemplo mais simples, em java, é esse daqui:

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;

/**
 * this is the cool stuff of writing mandelbrot set applet with
 * less than 512 bytes. But rickbit beats me with these 😛
 *
 *
 * @author girino
 *
 */
public class F extends Applet {

  public void paint(Graphics g) {
	  int j = -1;
	  while(++j<300) {
		  int i = -1;
		  while(++i<300) {
			  float x = 0f;
			  float y = 0f;
			  int v = 0;
			  for(; v < 40 && (x * x + y * y)/2f < 2f; v++) {
				  float t = i/100f - 2f + x * x - y * y;
				  y = j/100f - 1.57f + x * y * 2f;
				  x = t;
			  }
			  g.setColor(new Color(0f, (v==40)?0f:(float)Math.pow(v, 1f/2f)/6.325f, 0f));
			  g.drawRect(i,j,1,1);
		  }
	  }
  }

}

Pode reparar nesse código as seguintes linhas:

float t = i/100f - 2f + x * x - y * y;
y = j/100f - 1.57f + x * y * 2f;
x = t;

onde ele calcula a fórmula de Mandelbrot. Se você substituir isso por qualquer outra fórmula vai funcionar igualzinho. A divisão por

100f

é a tal "escala" que eu falei. Cada ponto da tela corresponde a tfrac{1}{100} de ponto na "vida real". (falar em real quando os números são imaginários é fogo!).

Na linha:

g.setColor(new Color(0f, (v==40)?0f:(float)Math.pow(v, 1f/2f)/6.325f, 0f));

Eu "pinto" com uma cor qualquer. Na verdade a cor depende de v que é a variável do tempo ede escape. Se for 40 (o máximo) eu pinto de preto, senão eu escolho um tom de verde numa escala exponencial. Qualquer formula que use v como parâmetro pode ser usada aqui para escolher a cor. Eu usei essa porque ela potencializa bem os detalhes. "Traduzindo" esta fórmula pra linguagem de gente temos:

vermelho = 0,   azul = 0,   verde =  begin{cases}  0, & v = 40 \  frac{sqrt{v}}{6,325}, & v < 40 end{cases}.

O resto não tem muito a ver com o fractal, é mais coisas da linguagem java, então eu deixo sem explicar mesmo.

Outras fórmulas

Existem variações em cima do conjunto de Mandelbrot, com a mesma técnica de cálculo, mas fórmulas diferentes. Os mais famosos são os conjuntos de Julia, que são calculados em cima dos pontos do conjunto mandelbrot, fazendo figurinhas bonitinhas assim:

A fórmula para calcular essas coisinhas bonitinhas depende de escolhermos um ponto inicial C no conjunto de mandelbrot, e deixar este ponto fixo! A fórmula também é igualzinha a do Mandelbrot:

Z_{n+1} = Z_{n}^{2} + C, Z_{0} = 0

Então o que muda? Simples! o valor inicialde Z0 não é mais 0! Agora o ponto da tela ao invés de ser o valor de C, é o valor de Z0. Aí temos figurinhas diferentes dependendo do valor de C que escolhemos. Não é o máximo?

Navio em chamas

Mais uma variaçãozinha famosa. O Burning Ship. Esse muda a fórmula, e o valor inicial vai dentro do C mesmo, tudo igual o mandelbrot. Mas a fórmula é essa:

Z_{n+1} = (|Re {Z_n}|+i|Im {Z_n}|)^2 + C

E que diabos é isso? Bom, Re é a parte real do número e Im é a parte imaginária. Quem não entende nada de matemática complexa, em java isso fica assim:

double xnplus1 = xn*xn - yn*yn - x;
yn = 2 * Math.abs(xn*yn) - y;
xn = xnplus1;

Simples? É como sempre, só mudar a fórmula! Pra quem ficou curioso, o navio em chamas faz figuras assim:

Variações bestas em cima do Mandelbrot

Existem, é claro, dúzias de variações bestas em cima do mandelbrot. Mudar o expoente de 2 pra 3, 4 ou 5, por exemplo. O resultado, em geral, é duplicar, triplicar, quadruplicar, etc, a figura original. Alguns exemplos:

  • Applet mudando o expoente para 3: Z_{n+1} = Z_{n}^{3} + C, Z_{0} = 0.
  • Applet mudando o expoente para 4: Z_{n+1} = Z_{n}^{4} + C, Z_{0} = 0.
  • Applet mudando o expoente para 5: Z_{n+1} = Z_{n}^{5} + C, Z_{0} = 0.

Mandelbar

É também mais uma variaçãozinha boba. Usa-se o conjugado complexo (para leigos, isso é mudar o sinal da parte complexa sem afetar a parte real) bar{Z} ao invés de Z puro: Z_{n+1} = bar{Z_{n}}^{2} + C, Z_{0} = 0.

Final

Bom, este tutorial ficou longo, mas acho que dá uma idéia geral desse tipo de fractal. Quem tiver sugestões ou comentários, clica naquela abinha "discussão" que tem lá no alto da página e deixa uns comentários por lá! Eu respondo ou incorporo as sugestões assim que possível. Querendo mudar o texto pra corrigir algum defeito, manda bala. É só clicar em editar. Não prometo que não vou remover suas mudanças (não, aqui não é a Wikipedia, é minha página pessoal mesmo!), mas se forem boas elas ficam sim.

E pra todos que leram até aqui, espero que tenham gostado. E obrigado pela atenção.

One thought on “Fractal - Um tutorial

  1. Oi Girino!
    Faço curso de matemática e gostaria de mais explicações. Vc pode me mandar, pois não estou conseguindo construir a figura em java. Aguardo.

Leave a Reply