
Introdução
Saudações todo mundo, saúde, saúde todo mundo!
Neste artigo, vou explicar como desenvolvi um programa em C (usando a biblioteca gráfica, a minilibx), para calcular, renderizar e explorar fractais.
O projecto foi feito inteiramente em C; Então, presumo que quem está lendo este artigo saiba o básico dessa linguagem, pelo menos até ponteiros e estruturas de dados.
Requisitos
Antes de começar a gerar código, quer dizer, escrever código, eu defini os requisitos funcionais básicos que meu programa deve atender:
Meu programa deve renderizar os conjuntos Mandelbrot, Burning Ship e Julia com suas variações.
Deve ser possível fazer zoom usando a roda do mouse. O zoom deve ser realizado em referência ao ponto indicado pelo cursor.
Usar um parâmetro para definir qual fractal será renderizado.
Poder trocar a paleta de cores dos fractais em tempo de execução.
As teclas de direção do teclado devem permitir a movimentação da visualização.
Implementação
Objetivos definidos, vamos à implementação! Farei com que o programa funcione como um utilitário de terminal, ou seja, ele será executado a partir da linha de comando, facilitando a passagem dos parâmetros ao executar. No entanto, você, caro leitor, pode implementá-lo da maneira que preferir.
Dessa maneira:
./fractol <parametro1> <parametro2> ... <parametroN>
Ainda não defini quais serão os possíveis parâmetros, mas quero fazer o mais simples possível. No entanto, essa abordagem parece superficial, pois os parâmetros apenas determinarão qual fractal renderizar, sem considerar outras funcionalidades que poderiam enriquecer a experiência do usuário. Então, você pode ir além e adicionar parâmetros que definam o tamanho da tela, a escala do zoom, a paleta de cores, etc. Por enquanto, vou me concentrar nisso, mas estou animado com as possibilidades futuras!
./fractol mandelbrot
# ou
./fractol burning-ship
# ou
./fractol julia
Se um desses parâmetros for passado na execução do programa, o fractal correspondente será renderizado.

Atualmente, estamos usando argv e argc, que são parâmetros que podem ser passados para um programa em C durante a execução. Eles são declarados na função main.
int main(int argc, char **argv) {
return (0);
}
Uma breve explicação sobre essas variáveis e sobre os argumentos passados pela linha de comando, para evitar confusões no futuro:
int argc (Contagem de Argumentos): Representa o número de argumentos passados, incluindo o nome do programa.
char *argv[] (Vetor de Argumentos): Um array de strings onde cada string corresponde a um argumento da linha de comando.
argv[0]geralmente contém o nome do programa ou o comando de invocação.argv[1],argv[2]e assim por diante armazenam os argumentos subsequentes fornecidos pelo usuário.
Em outro arquivo de código, criei a função int config_from_arg(int argc, char **argv, t_config *conf), que serve para um propósito específico: inicializar os valores da estrutura referenciada pelo ponteiro conf com valores que definem as configurações iniciais do programa para renderizar um fractal.
int config_from_arg(int ac, char **av, t_config *conf)
{
t_complex c;
if (ac == 2)
{
if (!strdiff(av[1], "mandelbrot"))
return (config_mandelbrot(conf), 1);
else if (!strdiff(av[1], "ship"))
return (config_burning_ship(conf), 1);
}
if (ac == 4)
{
if (!strdiff(av[1], "julia"))
{
if (!get_complex_value(&c, av[2], av[3]))
return (0);
config_julia(conf, c);
return (1);
}
}
return (0);
}
Não saia do artigo ainda, calma, eu vou explicar tudo isso que acabei de escrever.
Se eu estivesse lendo este artigo pela primeira vez, acho que acharia o t_config *conf um pouco estranho. Não porque seja algo complicado ou de outro mundo, mas simplesmente porque não sei como ele é declarado, de onde veio, ou para que será usado.
Adiante, *conf é um ponteiro que aponta para uma estrutura alocada estaticamente na pilha de memória. Ele virá da função main quando eu mostrar a implementação da função main, ou seja, a função config_from_arg. Mas isso não é o mais importante agora. Vamos nos concentrar nessa função e primeiro ver como a estrutura t_config é por dentro!
typedef struct s_config
{
int type;
int palette;
int max_iter;
t_complex c;
t_screen s;
} t_config;
Boa, é isso!
OK, eu explico, essa é a declaração de como serão as estruturas que definirão as configurações da renderização dos fractais a cada execução do programa. Essa informação será guardada em seus atributos.
O primeiro atributo declarado, type, do tipo int, simplesmente indicará ao programa qual tipo de fractal estamos renderizando. Cada um dos três fractais será identificado por um número de 0 a 2: 0 para Mandelbrot, 1 para Burning Ship e 2 para Julia. Até aqui tudo bem, certo? Se não, sinta-se à vontade para me enviar um e-mail para fevunge@outlook.com, e eu responderei prontamente.
Essa estrutura de dados é essencial para que o programa saiba qual fractal deve ser processado e exibido. Ao receber os parâmetros de entrada do usuário, a função config_from_arg atribuirá o valor correspondente ao atributo type dentro da configuração conf, garantindo que o fractal correto seja renderizado conforme a escolha do usuário.
A função config_from_arg será explicada detalhadamente mais à frente, não esqueça.
Mas ainda temos outros atributos que representam outras configurações. O palette definirá qual paleta de cores será usada na renderização do fractal. Esse atributo também mudará em tempo de execução, devido ao requisito número 4 da nossa lista de requisitos funcionais básicos, verifique.
O max_iter terá valor estático no meu código (independente dos parametros passados), por agora, mas deixo aí para permitir a escalabilidade de uma funcionalidade que quero adicionar depois. Depois de analisarmos o código, você pode decidir se quer alterar isso ou não.
Surgiram dois tipos de dados diferentes e interessantes, t_complex e t_screen, eles tambem sao estruturas de dados, CLARO! Eis suas declaracoes:
typedef struct s_screen
{
double r_low;
double r_top;
double i_low;
double i_top;
} t_screen;
typedef struct s_complex
{
double real;
double imag;
} t_complex;
Nada de estranho aqui, só duas coisas essenciais para desenhar um fractal, seja no computador ou no papel: uma tela (t_screen) e números complexos (t_complex). Muitos números complexos, mas isso é papo para outra aula. Vamos fazer uma introdução básica, só para mostrar que eu sei!
t_screen no meu programa representa um plano imaginário, semelhante ao plano cartesiano que aprendemos na escola. A diferença é que ele inclui números que não estão na linha real, conhecidos como números imaginários. Provavelmente é daí que vem o nome. Simplificando, é um plano 2D onde a linha horizontal, X, contém todos os números reais, e a linha vertical, Y, contém todos os números imaginários.

…
…
