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