
/**************************************************************************/
/* feigenbaum3.c                                               01.11.87   */
/* Version 1.1                                                            */
/*                                                                        */
/*                                                                        */
/* Demonstration eines Feigenbaums                                        */
/* unter farblicher Auswertung der Hauefigkeiten, 3 dimensionaler Dar-    */
/* stellung und Eingabemoeglichkeit der Parameter aus dem CLI.            */
/*                                                                        */
/* fuer Markt+Technik geschrieben von Heiko Knappe                        */
/*                                                                        */
/* Komplexe Dynamische Systeme                                            */
/* Feigenbaeume - ein Wachstumsproblem                                    */
/**************************************************************************/


#include <exec/types.h>
#include <intuition/intuition.h>

#define WIDTH  640     /* Screen Modus */
#define HEIGHT 500
#define DEPTH  3
#define FLAGS  HIRES+LACE

/* Definition der 'Feldgroesse' fuer die 3-d Ausgabe */
#define FWIDTH   400
#define FHEIGHT  200
#define FXOFFSET 20
#define FYOFFSET 150
#define OFF      10

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

int anzcol;
int n0=50,n1=200;          /* Offsets fuer die Iteration       */
float p0=.1,p;             /* Start-Population                 */
float kmin=1.9,kmax=3;     /* Relative Wachstums-Rate min/max  */
float st;
float k;                   /* Relative Wachstums-Rate          */
int n;                     /* Anzahl der Iterationen           */


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

main(argc,argv)
int argc;
char *argv[];
{
 int i;

 if((argc!=2)&&(argc!=1))
 {
    printf("Usage: %s <n0,n1,kmin,kmax,p0>\n",argv[0]);
    close_things();
 }
 if(argc==2)
    if(sscanf(argv[1],"%d,%d,%f,%f,%f",&n0,&n1,&kmin,&kmax,&p0)!=5)
    {
       printf("falsche Eingabe\n");
       close_things();
    }
 printf("Parameter:\n n0=%d n1=%d\n kmin=%f kmax=%f p0=%f\n",
        n0,n1,kmin,kmax,p0);
 for(i=1,anzcol=1;i<=DEPTH;++i,anzcol*=2)  /* Anzahl der Farben berechnen */
 st=(kmax-kmin)/FWIDTH;
 k=kmin;
 open_things();
 feigenbaum();
 while(MyScreen->TopEdge<100);
 close_things();
}


/***********************/
/* 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();
 rp=&(MyScreen->RastPort);
 init_colors();
 SetAPen(rp,3);
 Move(rp,10,10);
 Text(rp,"Komplexe Dynamische Systeme",27);
 Move(rp,10,21);
 Text(rp,"p=p*(1+k*(1-p))",15);
} 


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


init_colors()
{
 int i;

 for(i=0;i<anzcol;++i)
    SetRGB4(&(MyScreen->ViewPort),i,(int)((float)i/(float)anzcol*16),0,
            (int)((1-(float)i/(float)anzcol)*16));
}


/***********************/
/* Berechnung          */
/***********************/

feigenbaum()
{
 int i,x,ys,ye,anz[FHEIGHT];
 short color;

 for(k=kmin;k<kmax;k+=st)
 {
    if(MyScreen->TopEdge>100)
       return(0);
    p=p0;
    for(i=0;i<FHEIGHT;++i)                   /* Loeschen              */
       anz[i]=0;
    for(p=p0,n=0;n<(n0+n1);++n)              /* Werte berechnen       */
    {
        p=p*(1+k*(1-p));
        i=FHEIGHT*(1-p/2);
        if(n>=n0&&i<FHEIGHT&&i>=0) ++anz[i]; /* Unterdruecken         */
    }
    for(i=0;i<FHEIGHT;++i)                   /* Ausgabe               */
    {
       if(anz[i]!=0) color=anz[i]%(anzcol-1)+1;
       else color=0;
       SetAPen(rp,color);
       x=(k-kmin)/st+FXOFFSET+(FHEIGHT-i);
       ys=FYOFFSET+i;
       ye=ys-anz[i]-OFF;
       if(ys>HEIGHT) ys=HEIGHT;
       if((x>0)&&(x<WIDTH)&&(ys>0)&&(ys<HEIGHT)&&(color!=0))
       {
          Move(rp,x,ys);
          if(ye<0) ye=0;
          Draw(rp,x,ye);
          SetAPen(rp,anzcol-color);
          WritePixel(rp,x,ye);
       }
    }
 }
}
