home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 100.lha / IfsDraw / ifsdraw.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  12KB  |  408 lines

  1. /* IFSDraw.c  Copyright Charles Fritchie, Jr., 1987, 1988. */
  2. /* Compile with -cc flag (embedded comments). */
  3.  
  4. /* This program and code may be used freely for noncommercial or
  5.    nonprofit purposes provided this copyright notice is maintained 
  6.    intact.  No part may be used commercially without explicit
  7.    written permission of the author. */
  8.  
  9. /* Draws patterns by the iterated function systems approach
  10.    described in BYTE, January, 1988, pp 215-223.  Article by 
  11.    Michael F. Barnsley and Alan D. Sloan. */
  12.  
  13. /* Code examples in Jim Kent's IFF display program Plop and 
  14.    Vincent Hopson's menu program in AmigaWorld are gratefully
  15.    acknowledged. */
  16.  
  17. /* Usage is 'IFSDraw datafile'. */
  18. /* Program reads drawing data from a file with the following
  19.    format:
  20.    bkcol,drcol - two rgb color triads in hexadecimal used for
  21.      background and drawing colors.  Program uses 4 bitplanes, but
  22.      only these two colors (0 and 1) are normally used.
  23.    numtran - number of transformations following.  Program is
  24.      dimensioned for up to MAXDIM=9 transformations;  change MAXDIM
  25.      if more are needed.
  26.    xoff,yoff,xscale,yscale - x and y offsets in pixels, then x and
  27.      y scale factors in pixels, as described in article.  These can
  28.      best be determined by a trial plot.  Program uses 640 x 200
  29.      screen.
  30.    ma,mb,mc,md,me,mf,mp (numtran sets)  The 2x2 matrix, translation 
  31.      and probability for each transformation, as described in
  32.      article.  The sum of all probabilities should be 1.
  33. */
  34.  
  35. /*
  36. Sample data set for fern leaf:
  37. 555 3b5
  38. 4
  39. 200 20 20 15
  40. .85 .04 -.04 .85 0 1.6 .85
  41. -.15 .28 .26 .24 0 .44 .07
  42. .20 -.26 .23 .22 0 1.6 .07
  43. 0 0 0 .16 0 0 .01
  44. */
  45.  
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <math.h>
  49. #include <intuition/intuition.h>
  50. #include <exec/types.h>
  51. #include <exec/nodes.h>
  52. #include <exec/lists.h>
  53. #include <exec/libraries.h>
  54. #include <graphics/text.h>
  55. #include <graphics/display.h>        
  56. #include <graphics/gfx.h>
  57. #include <graphics/rastport.h>
  58. #include <graphics/view.h>
  59.  
  60. #define PARANOID /* Print debugging info */
  61. /* #define DEBUG */
  62.  
  63. #define XMAX 640
  64. #define YMAX 200
  65. #define PLANES 4
  66. #define MAXCOLORS (1<<PLANES)
  67. #define MAXDIM 9
  68.  
  69. extern struct Menu IFSMenu[]; /* Our menu */
  70. extern struct Library *OpenLibrary();
  71. extern struct Screen *OpenScreen();
  72. extern struct Window *OpenWindow();
  73.  
  74. struct Library *GfxBase = NULL;
  75. struct Library *LayersBase = NULL;
  76. struct Library *IntuitionBase = NULL;
  77. struct Screen *ifsScreen = NULL;
  78. struct Window *ifsWindow = NULL;
  79.  
  80. static struct NewScreen ifsNewScreen =
  81.     {
  82.     0, 0, XMAX, YMAX, PLANES,
  83.     0, 1,
  84.     0,
  85.     CUSTOMSCREEN,
  86.     NULL,
  87.     "IFSDraw",
  88.     NULL,
  89.     NULL,
  90.     };
  91.  
  92. static struct NewWindow ifsNewWin =
  93.     {
  94.     0, 0, XMAX, YMAX,
  95.     0, 1,
  96.         MENUPICK | CLOSEWINDOW,    /* IDCMP FLAGS */
  97.     WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH |BORDERLESS | ACTIVATE,
  98.                                  /* Flags */    
  99.     NULL,
  100.     NULL,
  101.     "IFS Window",  /* Title */
  102.     NULL,
  103.     NULL,
  104.     XMAX,YMAX,XMAX,YMAX,
  105.     CUSTOMSCREEN
  106.     };
  107. struct RastPort ifsRP;
  108.  
  109. UWORD colormap[MAXCOLORS] = {
  110.    0x888,    0x050,    0x40b,    0xff0,
  111. /* m.gray    md.green    m.viol    bt.yell */
  112.    0x0d0,    0x0b0,    0x090,    0xa84,
  113. /* ml.green  m.green   m.green   m.cyan     */
  114.    0x050,    0x888,    0x40b,    0xff0,
  115. /* md.green  m.gray    m.viol    bt.yell */
  116.    0x0d0,    0x0b0,    0x090,    0xa84
  117. /* ml.green  m.green   m.green   m.cyan     */
  118. };
  119.  
  120. /*--------- End declarations ----------*/
  121.  
  122. FILE *filep; /* File with transformations, etc. */
  123. int co,xlim,ylim,numtran,maxtran;
  124. float ma[MAXDIM],mb[MAXDIM],mc[MAXDIM],md[MAXDIM],me[MAXDIM],
  125.      mf[MAXDIM],mp[MAXDIM],totprob;
  126.      /* Matrix, translation and probabilities */
  127. float xoff,yoff,xscale,yscale; /* Plotting transform */
  128.  
  129. /*-----------------------------------------------------*/
  130. main(argc, argv)
  131. int argc;
  132. char *argv[];
  133. {
  134. void setup(); /* Load libraries, etc. */
  135. void loadnote(); /* Print load message to check menu */
  136. void savenote(); /* Print save message to check menu */
  137. void ifs_cleanup(); /* Give back memory */
  138. void print_cleanup();
  139.  
  140. struct IntuiMessage *message; /* Intuimessage pointer */
  141.  
  142. int mennum,menitem,mensubit; /* Menu selections */
  143. int numpts=2500; /* Points per call */
  144. /* Check arguments here, print usage note if wrong */
  145. if (argc<2) /* Must be 1 file */
  146.   {
  147.   printUsage();
  148.   return(-4);
  149.   }
  150. #ifdef DEBUG
  151.   puts(argv[1]);
  152. fflush(stdout);
  153. #endif DEBUG
  154.  
  155.     if (readfile(argv[1]) != 0)   /* Test for datafile read */
  156.       {
  157. #ifdef PARANOID
  158.       printf("couldn't load %s as a data file\n", argv[1]);
  159. #endif PARANOID
  160.       ifs_cleanup(-1);
  161.       }
  162.  
  163. if (ifsNewScreen.Width > 320)  /* Set flags for screen type */
  164.   ifsNewScreen.ViewModes |= HIRES;
  165. if (ifsNewScreen.Height > 200)
  166.   ifsNewScreen.ViewModes |= LACE;
  167.  
  168. setup(); /* Get libs, screen, etc. */
  169.  
  170. /* Load our colormap */
  171. LoadRGB4(&ifsScreen->ViewPort,colormap,32);
  172.     
  173. /* Setup menustrip, get rastport */    
  174. SetMenuStrip(ifsWindow, IFSMenu);
  175. InitRastPort(&ifsRP);
  176.  
  177. #ifdef DEBUG
  178. puts("RastPort up");
  179. fflush(stdout);
  180. #endif DEBUG    
  181.  
  182. /* Got window up; test menu. */
  183.  
  184.   for (;;) /* Loop until CloseGadget message  */
  185.   {
  186.     /* WaitPort waits for message port to become
  187.      not empty, and extracts message. */  
  188.     WaitPort(ifsWindow->UserPort);
  189.     message = (struct IntuiMessage *)GetMsg(ifsWindow->UserPort);
  190.     if ((message->Class) == MENUPICK) /* Is message a menu msg? */
  191.     {
  192.        if ((message->Code) != MENUNULL)
  193.          {
  194.          mennum=MENUNUM(message->Code);
  195.          menitem=ITEMNUM(message->Code);
  196.          mensubit=SUBNUM(message->Code);
  197.          if (mennum == 0)                   /* only current case */
  198.            if (menitem == 0)                /* (re)start */
  199.              ifsdraw(&ifsScreen->RastPort,0,numpts); 
  200.            else if (menitem == 1)           /* more */
  201.              {if (mensubit == 0)                /* x 1 */
  202.                ;
  203.              else if (mensubit == 1)            /* x 2 */
  204.                numpts= (2*numpts<10000) ? 2*numpts : 10000;
  205.              else if (mensubit == 2)            /* x 1/2 */
  206.                numpts= (numpts/2>100) ? numpts/2 : 100;
  207.              ifsdraw(&ifsScreen->RastPort,1,numpts); 
  208.              }
  209.            else if (menitem == 2)
  210.              break;                         /* quit */
  211.            else break; /* Default menitem; should never get here */    
  212.          else break; /* Default mennum; should never get here */  
  213.          }
  214.        ReplyMsg(message); /* Reply to MENUPICK message */
  215.     }  /* End if(MENUPICK) clause */  
  216.     else break; /* Not menu selection, must be closegadget. */
  217.   }  /* End for(;;) */
  218.   ReplyMsg(message); /* Reply to CLOSEGADGET message */
  219.   ClearMenuStrip(ifsWindow); /* Remove menustrip */
  220.  
  221. ifs_cleanup(0); /* Finished; get out */
  222. return(0);
  223.  
  224. /*-----------------------------------------------------*/
  225. void setup() /* Get libraries, screen, window */
  226. {
  227. void ifs_cleanup();
  228. if ((GfxBase = OpenLibrary("graphics.library", (long)0)) == NULL)
  229.   {
  230. #ifdef PARANOID
  231.   printf("Can't open Graphics Library\n");
  232. #endif PARANOID
  233.   ifs_cleanup(-2);
  234.   }
  235. if ((LayersBase = OpenLibrary("layers.library", (long)0)) == NULL)
  236.   {
  237. #ifdef PARANOID
  238.   printf("Can't open Layers Library\n");
  239. #endif PARANOID
  240.   ifs_cleanup(-3);
  241.   }
  242. if ((IntuitionBase = OpenLibrary("intuition.library",(long)0)) == NULL)
  243.   {
  244. #ifdef PARANOID
  245.   printf("Can't open Intuition Library\n");
  246. #endif PARANOID
  247.   ifs_cleanup(-4);
  248.   }
  249. if ((ifsScreen = OpenScreen(&ifsNewScreen)) == NULL)
  250.   {
  251. #ifdef PARANOID
  252.   printf("OpenScreen failed\n");
  253. #endif PARANOID
  254.   ifs_cleanup(-5);
  255.   }
  256. ifsNewWin.Screen = ifsScreen; /* Attach window to our screen */
  257. if ((ifsWindow = OpenWindow(&ifsNewWin)) == NULL)
  258.   {
  259. #ifdef PARANOID
  260.   printf("OpenWindow failed\n");
  261. #endif PARANOID
  262.   ifs_cleanup(-6);
  263.   }
  264. }
  265. /*-----------------------------------------------------*/
  266. readfile(fname)
  267. char *fname;
  268. {
  269. unsigned int ii;
  270. unsigned int bkcol,drcol; /* hex rgb values for background and
  271.                               drawing colors */
  272.   if ((filep = fopen(fname, "r") ) == 0) /* File found? */
  273.     {
  274.     printf("couldn't Open %s to read\n",fname);    
  275.     ifs_cleanup(-7);
  276.     }
  277.   /* Read 2 hex rgb sets for background, drawing */
  278.   if  (fscanf(filep,"%x %x",&bkcol,&drcol)!=2)
  279.     {
  280.     fclose(filep);
  281.     ifs_cleanup(-8);
  282.     }
  283.   colormap[0]=bkcol&0xfff; /* Move to colormap */
  284.   colormap[1]=drcol&0xfff;
  285.   /* Read numtran */
  286.   if  (fscanf(filep,"%d",&numtran)!=1)
  287.     {
  288.     fclose(filep);
  289.     ifs_cleanup(-8);
  290.     }
  291.   if (numtran>MAXDIM) /* Can't exceed dimensions */  
  292.     {printf("Program is dimensioned for %d transformations\n",MAXDIM);
  293.     fclose(filep);
  294.     ifs_cleanup(-9);
  295.     }    
  296.   maxtran=numtran-1; /* Need max index value */
  297.  
  298.   if (fscanf(filep,"%f %f %f %f",&xoff,&yoff,&xscale,&yscale)!=4)
  299.     {
  300.     fclose(filep);
  301.     ifs_cleanup(-10);
  302.     }
  303.   totprob=0; /* Cumulative probability */
  304.   for (ii=0;ii<numtran;ii++)   /* Read transformations */
  305.     {if (fscanf(filep,"%f %f %f %f %f %f %f",&ma[ii],&mb[ii],
  306.             &mc[ii],&md[ii],&me[ii],&mf[ii],&mp[ii])!=7)
  307.                       /* Need 7 items per line */
  308.       {
  309.       fclose(filep);
  310.       ifs_cleanup(-11);
  311.       }
  312.     totprob=totprob+mp[ii];  
  313.     mp[ii]=totprob;  /* Change probabilities to cumulative */
  314.     }
  315.   if(mp[maxtran]<1) mp[maxtran]=1; /* Force total probability >=1 */ 
  316.  
  317. #ifdef DEBUG
  318. puts("File reading finished\n");
  319. fflush(stdout);
  320. #endif DEBUG
  321. return(0);
  322. }
  323. /*-----------------------------------------------------*/
  324. ifsdraw(rPort,optn,numpts)
  325. struct RastPort *rPort;
  326. int optn; /* Option number */
  327. int numpts; /* Points to plot */
  328. {
  329. float prob,xp,yp; /* Random number, x and y on plotting scale */
  330. float xx=0;
  331. float yy=0; /* Initial coordinates */
  332. float xn,yn; /* Updated coordinates */
  333. float frandmax=pow((double)2,(double)31)-1;/* Max of rand() */
  334. int iuse;
  335. int inoplot=0;
  336. int col=1;
  337. unsigned short ii,jj,looplim; /* This gives fastest loops */
  338.  
  339. looplim=numpts;
  340. xlim = ifsWindow->Width-1;  /* Get width + height */
  341. ylim = ifsWindow->Height-1;    
  342. SetDrMd(rPort,JAM1); /* Set drawing mode */
  343.  
  344. if (optn==0)  /* (re)start */
  345.   {xx=yy=0; /* Initialize point */
  346.   SetAPen(rPort,0); /* Fill background */
  347.   RectFill(rPort,0,0,xlim,ylim);
  348.   inoplot=0; /* Counter for unplotted transforms */
  349.   }
  350.  
  351.     col = 1; /* Initial drawing color */
  352.     SetAPen(rPort,col); /* Set color */
  353.     for (jj=0;jj<looplim;jj++) /* Plot a bunch of points */
  354.     {prob=(rand()-1)/frandmax; /* Random number between 0 and <1.0 */
  355.     /* prob=drand48(); */  /* Can use this if pseudorandom process
  356.          repeats too soon, but about 25% slower */
  357.     iuse=0;
  358.     for (ii=0;prob>mp[ii];ii++)
  359.       iuse=ii+1; /* Select transformation */
  360.     if(iuse>maxtran) iuse=maxtran; /* Safety factor */  
  361.     xn=ma[iuse]*xx+mb[iuse]*yy+me[iuse]; /* Transform coords. */
  362.     yn=mc[iuse]*xx+md[iuse]*yy+mf[iuse];
  363.     xp=xoff+xscale*xn; /* Convert to pixel coordinates */
  364.     yp=yoff+yscale*yn;
  365.     if (xp>xlim) xp=xlim; /* Keep plotting within window */
  366.     if (xp<0) xp=0;
  367.     if (yp>ylim) yp=ylim;
  368.     if (yp<0) yp=0;
  369.  
  370.     if (inoplot<10)
  371.       {inoplot=inoplot+1; /* Skip first ten points */
  372. /*      printf("Prob,iuse,xp,yp= %f %d %f %f \n",prob,iuse,xp,yp); */
  373.       }
  374.     else
  375.       {WritePixel(rPort,(int)xp,(int)yp); /* Plot point */
  376.       }
  377.     xx=xn; /* Update point */
  378.     yy=yn;
  379.     } /* End for(jj) loop */
  380. return(0);
  381. }
  382.  
  383. /*-----------------------------------------------------*/
  384. void ifs_cleanup(retnum) /* back out backwards */
  385. int retnum; /* Return error code */
  386. {
  387. if (ifsWindow != NULL)  /* N.B. Should (?) check for IDCMP
  388.     messages before closing. */
  389.   CloseWindow(ifsWindow);
  390. if (ifsScreen != NULL)
  391.   CloseScreen(ifsScreen);
  392. if (IntuitionBase != NULL)
  393.   CloseLibrary(IntuitionBase);
  394. if (LayersBase != NULL)
  395.   CloseLibrary(LayersBase);
  396. if (GfxBase != NULL)
  397.   CloseLibrary(GfxBase);
  398. exit(retnum);
  399.  
  400. /*-----------------------------------------------------*/
  401. printUsage()
  402. {
  403. printf("Usage is 'datafile'\n");
  404. return(0);
  405.