Search
Write a publication
Pull to refresh

Множество Мандельброта на C

Давно любовался красивыми фракталами. Решил написать свою программу, которая будет их строить. Целью было получить что-то вроде такого изображения (взято с Википедии):

image

А получилось вот так:

image

Другой целью было получение максимально быстро работающей программы. Для этого исключил из расчета главную кардиоиду и самый большой круг. А еще сделал небольшую оптимизацию в самом внутреннем цикле. Получилось не слишком быстро — на моем компьютере 0,016 FPS для этого фрагмента. Правда, тут нужно много итераций и не попадает главная кардиоида.

Цвета подобрал отдаленно похожие. С чем не повезло — так это с мелкими красивыми деталями в нижней части. На их месте у меня почему-то мусор. Даже при 100000 итераций он не меняется. Вероятно, автор оригинальной картинки использовал другой алгоритм.

Собственно код
#include <stdio.h>
#include <math.h>
#include <time.h>
//Размеры и объем изображения
#define WIDTH 1280
#define HEIGHT 1024
#define VOLUME 3932160
size_t fwrite(const void *buf, size_t size, size_t count, FILE *stream);
clock_t clock(void);
int frame(double pcenter, double qcenter, double range);
FILE *fopen(const char *fname, const char *mode);
double Pmax, Pmin, Qmin;
//Хидер bmp файла
char head[]={0x42, 0x4D, 0x36, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
char results[VOLUME];
int main(void)
{
  double range, xcenter, ycenter;
  range=0.000000049304;
    xcenter=-0.743643900055;
    ycenter=0.131825890901;
    frame(xcenter, ycenter, range);
  FILE *str;
  str=fopen("output.bmp", "wb");
  fwrite(head, 1, 54, str);
  fwrite(results, 1, VOLUME, str);
  fclose(str);
  // FPS 
  printf("clock %.4f\n", 1.0*CLOCKS_PER_SEC/(1.0*(clock())));
  return 0;
}
int frame(double pcenter, double qcenter, double range)
{
  double dp, p, q, cardio;
  register double x, y, x2, y2, xtemp;
  register int i,j,n;
  int colwidth=666;
  int coloffset=3200;
  int nmax=24000;
  long int black=0;
  char *pres=results;
  
  Pmax=pcenter+range/2;
  Pmin=pcenter-range/2;
  Qmin=qcenter-range/2.5;
  dp=range/(WIDTH-1);
  for (j=0;j<HEIGHT;j++)
  {
  	 q=Qmin+j*dp;
    for (i=0;i<WIDTH;i++)
    {
      p=Pmin+i*dp;
//Исключаем то, что заведомо относится к множеству
      cardio=sqrt((p-0.25)*(p-0.25)+q*q);
      if (p<(cardio-2*cardio*cardio+0.25)||(p+1)*(p+1)+q*q<0.0625)
        {
        	 *pres=black;
          pres+=3;
        }
      else
      {
  	     x=y=x2=y2=n=0;
        while (x2+y2<4&&n<nmax)
        {
          xtemp=x2-y2+p;
          y=2*x*y+q;
          x=xtemp;
          x2=x*x;
          y2=y*y;
          n++;
        }
// Раскрашиваем
        if (n==nmax) 
        {
          *pres=black;
          pres+=3;
        }
        else 
        { 
          n=(n+coloffset)%(3*colwidth);
          if (n/colwidth==0)
          { // Голубой 116.11.0          
            *pres++=116+139*n/colwidth;//B
            *pres++=11+244*n/colwidth;//G
            *pres++=237*n/colwidth;//R
          }
          else if (n/colwidth==1)
          { // Белый 255.255.237
            n-=colwidth;
            *pres++=255-253*n/colwidth;//B
            *pres++=255-123*n/colwidth;//G
            *pres++=238;//R            
          }
          else 
          { // Рыжий 2.132.239
            n-=2*colwidth;
            *pres++=2+114*n/colwidth;//B
            *pres++=132-121*n/colwidth;//G
            *pres++=239-239*n/colwidth;//R
          }
        }
      }
    }
  }  
  return results[VOLUME];
}




Алгоритмы подсмотрел здесь: en.m.wikipedia.org/wiki/Mandelbrot_set
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.