home *** CD-ROM | disk | FTP | other *** search
- /* IFSDraw.c Copyright Charles Fritchie, Jr., 1987, 1988. */
- /* Compile with -cc flag (embedded comments). */
-
- /* This program and code may be used freely for noncommercial or
- nonprofit purposes provided this copyright notice is maintained
- intact. No part may be used commercially without explicit
- written permission of the author. */
-
- /* Draws patterns by the iterated function systems approach
- described in BYTE, January, 1988, pp 215-223. Article by
- Michael F. Barnsley and Alan D. Sloan. */
-
- /* Code examples in Jim Kent's IFF display program Plop and
- Vincent Hopson's menu program in AmigaWorld are gratefully
- acknowledged. */
-
- /* Usage is 'IFSDraw datafile'. */
- /* Program reads drawing data from a file with the following
- format:
- bkcol,drcol - two rgb color triads in hexadecimal used for
- background and drawing colors. Program uses 4 bitplanes, but
- only these two colors (0 and 1) are normally used.
- numtran - number of transformations following. Program is
- dimensioned for up to MAXDIM=9 transformations; change MAXDIM
- if more are needed.
- xoff,yoff,xscale,yscale - x and y offsets in pixels, then x and
- y scale factors in pixels, as described in article. These can
- best be determined by a trial plot. Program uses 640 x 200
- screen.
- ma,mb,mc,md,me,mf,mp (numtran sets) The 2x2 matrix, translation
- and probability for each transformation, as described in
- article. The sum of all probabilities should be 1.
- */
-
- /*
- Sample data set for fern leaf:
- 555 3b5
- 4
- 200 20 20 15
- .85 .04 -.04 .85 0 1.6 .85
- -.15 .28 .26 .24 0 .44 .07
- .20 -.26 .23 .22 0 1.6 .07
- 0 0 0 .16 0 0 .01
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <intuition/intuition.h>
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/libraries.h>
- #include <graphics/text.h>
- #include <graphics/display.h>
- #include <graphics/gfx.h>
- #include <graphics/rastport.h>
- #include <graphics/view.h>
-
- #define PARANOID /* Print debugging info */
- /* #define DEBUG */
-
- #define XMAX 640
- #define YMAX 200
- #define PLANES 4
- #define MAXCOLORS (1<<PLANES)
- #define MAXDIM 9
-
- extern struct Menu IFSMenu[]; /* Our menu */
- extern struct Library *OpenLibrary();
- extern struct Screen *OpenScreen();
- extern struct Window *OpenWindow();
-
- struct Library *GfxBase = NULL;
- struct Library *LayersBase = NULL;
- struct Library *IntuitionBase = NULL;
- struct Screen *ifsScreen = NULL;
- struct Window *ifsWindow = NULL;
-
- static struct NewScreen ifsNewScreen =
- {
- 0, 0, XMAX, YMAX, PLANES,
- 0, 1,
- 0,
- CUSTOMSCREEN,
- NULL,
- "IFSDraw",
- NULL,
- NULL,
- };
-
- static struct NewWindow ifsNewWin =
- {
- 0, 0, XMAX, YMAX,
- 0, 1,
- MENUPICK | CLOSEWINDOW, /* IDCMP FLAGS */
- WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH |BORDERLESS | ACTIVATE,
- /* Flags */
- NULL,
- NULL,
- "IFS Window", /* Title */
- NULL,
- NULL,
- XMAX,YMAX,XMAX,YMAX,
- CUSTOMSCREEN
- };
- struct RastPort ifsRP;
-
- UWORD colormap[MAXCOLORS] = {
- 0x888, 0x050, 0x40b, 0xff0,
- /* m.gray md.green m.viol bt.yell */
- 0x0d0, 0x0b0, 0x090, 0xa84,
- /* ml.green m.green m.green m.cyan */
- 0x050, 0x888, 0x40b, 0xff0,
- /* md.green m.gray m.viol bt.yell */
- 0x0d0, 0x0b0, 0x090, 0xa84
- /* ml.green m.green m.green m.cyan */
- };
-
- /*--------- End declarations ----------*/
-
- FILE *filep; /* File with transformations, etc. */
- int co,xlim,ylim,numtran,maxtran;
- float ma[MAXDIM],mb[MAXDIM],mc[MAXDIM],md[MAXDIM],me[MAXDIM],
- mf[MAXDIM],mp[MAXDIM],totprob;
- /* Matrix, translation and probabilities */
- float xoff,yoff,xscale,yscale; /* Plotting transform */
-
- /*-----------------------------------------------------*/
- main(argc, argv)
- int argc;
- char *argv[];
- {
- void setup(); /* Load libraries, etc. */
- void loadnote(); /* Print load message to check menu */
- void savenote(); /* Print save message to check menu */
- void ifs_cleanup(); /* Give back memory */
- void print_cleanup();
-
- struct IntuiMessage *message; /* Intuimessage pointer */
-
- int mennum,menitem,mensubit; /* Menu selections */
- int numpts=2500; /* Points per call */
- /* Check arguments here, print usage note if wrong */
- if (argc<2) /* Must be 1 file */
- {
- printUsage();
- return(-4);
- }
- #ifdef DEBUG
- puts(argv[1]);
- fflush(stdout);
- #endif DEBUG
-
- if (readfile(argv[1]) != 0) /* Test for datafile read */
- {
- #ifdef PARANOID
- printf("couldn't load %s as a data file\n", argv[1]);
- #endif PARANOID
- ifs_cleanup(-1);
- }
-
- if (ifsNewScreen.Width > 320) /* Set flags for screen type */
- ifsNewScreen.ViewModes |= HIRES;
- if (ifsNewScreen.Height > 200)
- ifsNewScreen.ViewModes |= LACE;
-
- setup(); /* Get libs, screen, etc. */
-
- /* Load our colormap */
- LoadRGB4(&ifsScreen->ViewPort,colormap,32);
-
- /* Setup menustrip, get rastport */
- SetMenuStrip(ifsWindow, IFSMenu);
- InitRastPort(&ifsRP);
-
- #ifdef DEBUG
- puts("RastPort up");
- fflush(stdout);
- #endif DEBUG
-
- /* Got window up; test menu. */
-
- for (;;) /* Loop until CloseGadget message */
- {
- /* WaitPort waits for message port to become
- not empty, and extracts message. */
- WaitPort(ifsWindow->UserPort);
- message = (struct IntuiMessage *)GetMsg(ifsWindow->UserPort);
- if ((message->Class) == MENUPICK) /* Is message a menu msg? */
- {
- if ((message->Code) != MENUNULL)
- {
- mennum=MENUNUM(message->Code);
- menitem=ITEMNUM(message->Code);
- mensubit=SUBNUM(message->Code);
- if (mennum == 0) /* only current case */
- if (menitem == 0) /* (re)start */
- ifsdraw(&ifsScreen->RastPort,0,numpts);
- else if (menitem == 1) /* more */
- {if (mensubit == 0) /* x 1 */
- ;
- else if (mensubit == 1) /* x 2 */
- numpts= (2*numpts<10000) ? 2*numpts : 10000;
- else if (mensubit == 2) /* x 1/2 */
- numpts= (numpts/2>100) ? numpts/2 : 100;
- ifsdraw(&ifsScreen->RastPort,1,numpts);
- }
- else if (menitem == 2)
- break; /* quit */
- else break; /* Default menitem; should never get here */
- else break; /* Default mennum; should never get here */
- }
- ReplyMsg(message); /* Reply to MENUPICK message */
- } /* End if(MENUPICK) clause */
- else break; /* Not menu selection, must be closegadget. */
- } /* End for(;;) */
- ReplyMsg(message); /* Reply to CLOSEGADGET message */
- ClearMenuStrip(ifsWindow); /* Remove menustrip */
-
- ifs_cleanup(0); /* Finished; get out */
- return(0);
- }
-
- /*-----------------------------------------------------*/
- void setup() /* Get libraries, screen, window */
- {
- void ifs_cleanup();
- if ((GfxBase = OpenLibrary("graphics.library", (long)0)) == NULL)
- {
- #ifdef PARANOID
- printf("Can't open Graphics Library\n");
- #endif PARANOID
- ifs_cleanup(-2);
- }
- if ((LayersBase = OpenLibrary("layers.library", (long)0)) == NULL)
- {
- #ifdef PARANOID
- printf("Can't open Layers Library\n");
- #endif PARANOID
- ifs_cleanup(-3);
- }
- if ((IntuitionBase = OpenLibrary("intuition.library",(long)0)) == NULL)
- {
- #ifdef PARANOID
- printf("Can't open Intuition Library\n");
- #endif PARANOID
- ifs_cleanup(-4);
- }
- if ((ifsScreen = OpenScreen(&ifsNewScreen)) == NULL)
- {
- #ifdef PARANOID
- printf("OpenScreen failed\n");
- #endif PARANOID
- ifs_cleanup(-5);
- }
- ifsNewWin.Screen = ifsScreen; /* Attach window to our screen */
- if ((ifsWindow = OpenWindow(&ifsNewWin)) == NULL)
- {
- #ifdef PARANOID
- printf("OpenWindow failed\n");
- #endif PARANOID
- ifs_cleanup(-6);
- }
- }
- /*-----------------------------------------------------*/
- readfile(fname)
- char *fname;
- {
- unsigned int ii;
- unsigned int bkcol,drcol; /* hex rgb values for background and
- drawing colors */
- if ((filep = fopen(fname, "r") ) == 0) /* File found? */
- {
- printf("couldn't Open %s to read\n",fname);
- ifs_cleanup(-7);
- }
- /* Read 2 hex rgb sets for background, drawing */
- if (fscanf(filep,"%x %x",&bkcol,&drcol)!=2)
- {
- fclose(filep);
- ifs_cleanup(-8);
- }
- colormap[0]=bkcol&0xfff; /* Move to colormap */
- colormap[1]=drcol&0xfff;
- /* Read numtran */
- if (fscanf(filep,"%d",&numtran)!=1)
- {
- fclose(filep);
- ifs_cleanup(-8);
- }
- if (numtran>MAXDIM) /* Can't exceed dimensions */
- {printf("Program is dimensioned for %d transformations\n",MAXDIM);
- fclose(filep);
- ifs_cleanup(-9);
- }
- maxtran=numtran-1; /* Need max index value */
-
- if (fscanf(filep,"%f %f %f %f",&xoff,&yoff,&xscale,&yscale)!=4)
- {
- fclose(filep);
- ifs_cleanup(-10);
- }
- totprob=0; /* Cumulative probability */
- for (ii=0;ii<numtran;ii++) /* Read transformations */
- {if (fscanf(filep,"%f %f %f %f %f %f %f",&ma[ii],&mb[ii],
- &mc[ii],&md[ii],&me[ii],&mf[ii],&mp[ii])!=7)
- /* Need 7 items per line */
- {
- fclose(filep);
- ifs_cleanup(-11);
- }
- totprob=totprob+mp[ii];
- mp[ii]=totprob; /* Change probabilities to cumulative */
- }
- if(mp[maxtran]<1) mp[maxtran]=1; /* Force total probability >=1 */
-
- #ifdef DEBUG
- puts("File reading finished\n");
- fflush(stdout);
- #endif DEBUG
- return(0);
- }
- /*-----------------------------------------------------*/
- ifsdraw(rPort,optn,numpts)
- struct RastPort *rPort;
- int optn; /* Option number */
- int numpts; /* Points to plot */
- {
- float prob,xp,yp; /* Random number, x and y on plotting scale */
- float xx=0;
- float yy=0; /* Initial coordinates */
- float xn,yn; /* Updated coordinates */
- float frandmax=pow((double)2,(double)31)-1;/* Max of rand() */
- int iuse;
- int inoplot=0;
- int col=1;
- unsigned short ii,jj,looplim; /* This gives fastest loops */
-
- looplim=numpts;
- xlim = ifsWindow->Width-1; /* Get width + height */
- ylim = ifsWindow->Height-1;
- SetDrMd(rPort,JAM1); /* Set drawing mode */
-
- if (optn==0) /* (re)start */
- {xx=yy=0; /* Initialize point */
- SetAPen(rPort,0); /* Fill background */
- RectFill(rPort,0,0,xlim,ylim);
- inoplot=0; /* Counter for unplotted transforms */
- }
-
- col = 1; /* Initial drawing color */
- SetAPen(rPort,col); /* Set color */
- for (jj=0;jj<looplim;jj++) /* Plot a bunch of points */
- {prob=(rand()-1)/frandmax; /* Random number between 0 and <1.0 */
- /* prob=drand48(); */ /* Can use this if pseudorandom process
- repeats too soon, but about 25% slower */
- iuse=0;
- for (ii=0;prob>mp[ii];ii++)
- iuse=ii+1; /* Select transformation */
- if(iuse>maxtran) iuse=maxtran; /* Safety factor */
- xn=ma[iuse]*xx+mb[iuse]*yy+me[iuse]; /* Transform coords. */
- yn=mc[iuse]*xx+md[iuse]*yy+mf[iuse];
- xp=xoff+xscale*xn; /* Convert to pixel coordinates */
- yp=yoff+yscale*yn;
- if (xp>xlim) xp=xlim; /* Keep plotting within window */
- if (xp<0) xp=0;
- if (yp>ylim) yp=ylim;
- if (yp<0) yp=0;
-
- if (inoplot<10)
- {inoplot=inoplot+1; /* Skip first ten points */
- /* printf("Prob,iuse,xp,yp= %f %d %f %f \n",prob,iuse,xp,yp); */
- }
- else
- {WritePixel(rPort,(int)xp,(int)yp); /* Plot point */
- }
- xx=xn; /* Update point */
- yy=yn;
- } /* End for(jj) loop */
- return(0);
- }
-
- /*-----------------------------------------------------*/
- void ifs_cleanup(retnum) /* back out backwards */
- int retnum; /* Return error code */
- {
- if (ifsWindow != NULL) /* N.B. Should (?) check for IDCMP
- messages before closing. */
- CloseWindow(ifsWindow);
- if (ifsScreen != NULL)
- CloseScreen(ifsScreen);
- if (IntuitionBase != NULL)
- CloseLibrary(IntuitionBase);
- if (LayersBase != NULL)
- CloseLibrary(LayersBase);
- if (GfxBase != NULL)
- CloseLibrary(GfxBase);
- exit(retnum);
- }
-
- /*-----------------------------------------------------*/
- printUsage()
- {
- printf("Usage is 'datafile'\n");
- return(0);
- }
-