/* analog filmPlane.c nur Untersuchung von Julia-Mengen                   */
/**************************************************************************/
/* filmJulia.c                                                   29.12.87 */
/* Version 1.0                                                            */
/*                                                                        */
/*                                                                        */
/*                                                                        */
/* fuer Markt+Technik geschrieben von Heiko Knappe                        */
/*                                                                        */
/* Komplexe Dynamische Systeme                                            */
/**************************************************************************/


#include <exec/types.h>
#include <math.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>

#define WIDTH   320  /* Screen Modus */
#define HEIGHT  200
#define DEPTH   5
#define FLAGS   0
#define FWIDTH  320  /* falls nur ein kleinerer Ausschnitt berechnet */
#define FHEIGHT 200  /* werden soll. */
#define FXOFF   0
#define FYOFF   0

extern short save();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *MyScreen;
struct RastPort *MyRastPort;
struct NewScreen MyNewScreen=
 {0,0,WIDTH,HEIGHT,DEPTH,1,0,FLAGS,CUSTOMSCREEN,0,0,0,0};

int   n,nmax=100;            /* Iterationsschritte                  */
int   anz,bild;              /* Anzahl der Bilder                   */
float emin=.001,emax=100000; /* Abbruchkriterium                    */
float rmin=-1.5,rmax=2.5;    /* Grenzen des Bildes                  */
float imin=-1.2,imax=1.2;
float r1min,r1max,i1min,i1max,r2min,r2max,i2min,i2max;
float rst,ist,r1st,i1st,r2st,i2st;
float re,im,re1,re2,im1,im2,cre,cim;
                             /* re,im laufender Re- und Im-Teil     */
                             /* re1,re2,im1,im2  -> Folgenglieder   */
float d;                     /* Abstand zu dem Bezugspunkt          */
short x,y;                   /* Punktkoordinaten                    */
short anzcol,col,i;
char  file_name[20]="pic",num[10];


/***********************/
/* Hauptprogramm       */
/***********************/

main(argc,argv)
int argc;
char *argv[];
{
 if(argc!=3)
 {
    printf("Eingabe:\n %s <nmax,anz,r1min,r1max,i1min,i1max,",argv[0]);
    printf("r2min,r2max,i2min,i2max> <cre,cim>\n");
    printf(" nmax: maximale Anzahl der Duerchlaeufe\n");
    printf(" anz:  Anzahl der Bilder\n");
    printf(" [r1min,r1max][i1min,i1max]: Wertebereich des 1. Bildes\n");
    printf(" [r2min,r2max][i2min,i2max]: Wertebereich des letzten Bildes\n");
    printf(" cre,cim Konstante fuer Julia-Mengen\n");
    close_things();
 }
 if(sscanf(argv[1],"%d,%d,%f,%f,%f,%f,%f,%f,%f,%f",&nmax,&anz,
    &r1min,&r1max,&i1min,&i1max,&r2min,&r2max,&i2min,&i2max)!=10)
 {
    printf("falsche Eingabe\n");
    close_things();
 }
 if(sscanf(argv[2],"%f,%f",&cre,&cim)!=2)
 {
    printf("falsche Eingabe\n");
    close_things();
 }
 printf("\nParameter:\n emin=%f emax=%f\n",emin,emax);
 printf(" nmax=%d\n",nmax);
 printf(" c= %f+i*%f\n",cre,cim);
 printf(" erstes Bild:  [%f,%f] [%f,%f]\n",r1min,r1max,i1min,i1max);
 printf(" letztes Bild: [%f,%f] [%f,%f]\n",r2min,r2max,i2min,i2max);
 printf(" %d Bilder werden berechnet.\n",anz);
 emin*=emin;  /* mit dem Quadrat zu vergleichen erspart Wurzeln zu */
 emax*=emax;  /* berechnen -> Schnelligkeit                        */
 if(anz<=1) anz=2;
 open_things();
 r1st=(r2max-r1max)/(anz-1),i1st=(i2max-i1max)/(anz-1);
 r2st=(r2min-r1min)/(anz-1),i2st=(i2min-i1min)/(anz-1);
 rmin=r1min,rmax=r1max,imin=i1min,imax=i1max;
 for(bild=0;bild<anz;++bild,rmin+=r2st,rmax+=r1st,imin+=i2st,imax+=i1st)
 {
    itoa(bild,num);
    strcpy(file_name+3,num);
    printf("Berechnung Bild: %d -> %s\n      [%f,%f][%f,%f]\n",
           bild,file_name,rmin,rmax,imin,imax);
    mandel();
    if(save(file_name,1,MyScreen)!=TRUE) break; /* Fehler? */
 }
 close_things();
}

/* Hilfsfunktion (int nach ASCII) */
itoa(wert,buff)
int wert;
char buff[];
{
 int i,j,sign;
 char c;

 if((sign=wert)<0)
    wert=-wert;
 i=0;
 do
 {
    buff[i++]=wert%10+'0';
 }
 while((wert/=10)>0);
 if(sign<0)
    buff[i++]='-';
 buff[i]=0;
 for(i=0,j=strlen(buff)-1;i<j;i++,j--)
 {
    c=buff[i];
    buff[i]=buff[j];
    buff[j]=c;
 }
}


/***********************/
/* Initialisierung     */
/***********************/

open_things()
{
 if((IntuitionBase=OpenLibrary("intuition.library",0))==0)
    close_things();
 if((GfxBase=OpenLibrary("graphics.library",0))==0)
    close_things();
 if((MyScreen=OpenScreen(&MyNewScreen))==0)
    close_things();
 MyRastPort=&(MyScreen->RastPort);
 init_colors();
} 

close_things()
{
 if(IntuitionBase!=0) CloseLibrary(IntuitionBase);
 if(GfxBase!=0) CloseLibrary(GfxBase);
 if(MyScreen!=0) CloseScreen(MyScreen);
 exit(0);
} 

init_colors()
{
 for(i=0,anzcol=1;i<DEPTH;anzcol*=2,++i);
 for(i=0;i<anzcol/2;++i)
    SetRGB4(&(MyScreen->ViewPort),i,
            (short)((float)i/anzcol*15*2),0,0);
 for(i=anzcol/2;i<anzcol;++i)
    SetRGB4(&(MyScreen->ViewPort),i,15,0,
            (short)((float)(i-anzcol/2)/anzcol*15*2));
}


/***********************/
/* Bild-Berechnung     */
/***********************/

mandel()
{
 rst=(rmax-rmin)/FWIDTH;
 ist=(imax-imin)/FHEIGHT;
 for(x=0;x<FWIDTH;++x) /* in x-Richtung */
 {
    re=rmin+x*rst;
    for(y=0;y<FHEIGHT;++y) /* in y-Richtung */
    {
       /* Kontrollpunkt */
       SetAPen(MyRastPort,anzcol-1);
       WritePixel(MyRastPort,x+FXOFF,y+FYOFF);
       im=imin+y*ist;
       for(n=0,re1=re,im1=im;n<nmax;++n)
       {
          im2=2*re1*im1-cim,re2=re1*re1-im1*im1-cre;
          im1=im2,re1=re2;
          d=im1*im1+re1*re1;
          /* Ist der Attraktor erreicht? */
          if(d<emin)  break;
          /* Attraktor Unendlich? */
          if(d>emax)  break;
       }
       col=n%(anzcol-1)+1;
       if(n==nmax) col=0; /* unbestimmt -> schwarz */
       SetAPen(MyRastPort,col);
       WritePixel(MyRastPort,x+FXOFF,y+FYOFF);
    }
 }
}
