25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more...
Home   Projects   Up   Sitemap   Search   Blog   Forum+Chat   About Us   Privacy   Terms of Use   Feedback   FAQ   Images   Services   Payments   Humor   Music  

Display iterated function set fractal from an .IFS data file, DeSmet C, Heathkit H-100 computer 

This companion program to my automated continuous IFS fractal generator, instead of generating random IFS sets, loads its data from an .IFS file and displays the fractal image. 

The data can be from an .IFS a file (rectangular notation) or from a .PFS file (polar notation), and the program has three coloration options:

  • Monochrome (green)
  • By number of times the point is hit
  • By which transform generated the current point

The most recent incarnation of this program is an online calculator where you can design and display the fractal image on the web page.

/*	showfs.c    6-5-93
	Copyright (C)1993 Steven Whitney.
	Initially published by http://25yearsofprogramming.com.
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	Version 3 as published by the Free Software Foundation.
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

	READS FILE DATA FOR AN IFS (ITERATED FUNCTION SYSTEM) SET 
	AND CALCULATES AND DISPLAYS THE FRACTAL DESIGN THAT IT DEFINES.  	
	READS DATA FILE IN EITHER .IFS FORMAT (RECTANGULAR COORDINATES)
	OR .PFS FORMAT (POLAR). 
	.PFS FORMAT MAKES IT MUCH EASIER TO SEE THE RELATIONSHIPS BETWEEN
	THE NUMBERS AND THE IMAGES PRODUCED.

	Much of this program is quite similar to autorand.c, except that it can only 
	read its data from a file, and has no ability to generate its own new IFS sets.
	In a later incarnation (wshowfs.cpp, in Borland C++/OWL), the two programs were merged.

*/
#include "stdio.h"

#define zArray(a)	_setmem(a, sizeof(a), 0)

main(argc,argv)
int argc;
char *argv[];
{
int i;							/* temporary */
int t;							/* number of transforms */
int k;							/* transformation choice */
int polar = FALSE;				/* whether file is .IFS or .PFS */
int upsdwn = TRUE;				/* flag: whether to invert y axis */
int showequat = TRUE;			/* flag: whether to show equations */
int seed;						/* user inputs random number seed */
int tempx, tempy;				/* actual values to plot */
double a[20], b[20], c[20];		/* transform arrays */
double d[20], e[20], f[20];	
double p[20];					/* probabilities */
double cp[20];					/* stores probability thresholds */
double xr[20], ys[20];				/* polar x, y distances */
double theta[20], phi[20];			/* polar x,y axis rotations, in radians */
double thetaangle[20], phiangle[20];	/* (rotations in degrees) */
double r;						/* a random number */
double x, y, newx, newy;		/* screen coordinates */
double minx, maxx, miny, maxy;	/* screen limits */
double xrange, yrange;			/* screen ranges */
double xfactor, yfactor;		/* scaling factors */
long n;							/* counts iterations */
long nonpts = 400;				/* number of points to not display */
long throwout = 20;				/* points merely bring near attractor */
FILE *infile;
char fnam[81];					/* for holding input file name   */
char zicnam[81];				/* input file name, but with .ZED extension */
char ch = '\0';					/* tests for user keyboard input */
char dispmode = 'm';			/* display: Mono, Color by # hits, */
								/* color by Transform */

freeall(1024);					/* initializes malloc area, but in this */
								/* case, it only dups the default */

/* -------------------------------------------------------------- */
/*	HELP SCREEN */
/* -------------------------------------------------------------- */
if(argc == 1)					/* user only typed program name */
{
	puts("\nUsage:   SHOWFS  [path\\]datafile.ext  -options\n");
	puts("Example: showifs c:\\ifs\\infile.ifs  -rn\n");
	puts("         Extension must be .IFS or .PFS\n");
	puts("\nCOMMAND LINE OPTIONS:\n\n");
	puts("e = suppress initial display of ifs variables\n");
	puts("n = user will manually set # of initial unplotted points\n");
	puts("r = user will provide random number seed\n");
	puts("u = invert y axis for upside down image\n");
	puts("c = color determined by number of times a point is hit\n");
	puts("t = color determined by transform chosen for that point\n");
	puts("    (default color is mono: green)\n");
	puts("\nWHILE PROGRAM IS RUNNING:\n");
	puts("\nPress E to display (or re-display) equations.\n");
	puts("Press N to display number of points plotted so far.\n");
	puts("Press P to save screen to a picture file.\n");
	puts("Press Q to Quit.\n");
	exit(0);
}

/* -------------------------------------------------------------- */
/*	DEAL WITH INPUT & OUTPUT FILE NAMES */
/* -------------------------------------------------------------- */
if(argc > 1)				
{			
	strcpy(fnam,argv[1]);	
	if((infile = fopen(fnam,"r")) == NULL)
		abort("\nInput file not found.\n");
	strupr(fnam);
}										/* for use when naming .ZED file */
strcpy(zicnam,fnam);									/* copy file name */
if(!strcmp(index(zicnam,'.'),".PFS")) polar = TRUE;		/* test for .PFS */
*(index(zicnam,'.')) = '\0';	/* change period to a null (end string) */
strcat(zicnam,".ZED");			/* add .ZED extension instead */

/* -------------------------------------------------------------- */
/*	INTERPRET COMMAND LINE OPTIONS */
/* -------------------------------------------------------------- */
if(argc == 3)				
{
	if(index(strlwr(argv[2]),'c')) dispmode = 'c';	/* color by # hits */
	if(index(strlwr(argv[2]),'t')) dispmode = 't';	/* color by transform */
	if(index(strlwr(argv[2]),'u')) upsdwn = FALSE;	/* upside down image */
	if(index(argv[2],'e')) showequat = FALSE;		/* don't show numbers */
	if(index(argv[2],'n'))				
	{
		puts("\nEnter number of initial unplotted points: ");
		scanf("%ld",&nonpts);
	}
	if(index(argv[2],'r'))
	{
		puts("\nEnter random number seed (-32768 to 32767): ");
		scanf("%d",&seed);
		srand(seed);
	}
}

/* -------------------------------------------------------------- */
/*	INITIALIZATIONS */
/* -------------------------------------------------------------- */
puts("\033z");				/* reset terminal */
puts("\033x1");				/* enable 25th line */
puts("\033x<\033y@");		/* disable keyboard auto-repeat & event mode */
_outb(0x78,0xD8);  			/* video port D8: all enabled & separate */

zArray(a); zArray(b); zArray(c); zArray(d); 	/* initialize arrays */
zArray(e); zArray(f); zArray(p); zArray(cp);	/* to zero */
zArray(xr); zArray(ys); zArray(theta); zArray(phi);
zArray(thetaangle); zArray(phiangle);

/* -------------------------------------------------------------- */
/*	READ DISK FILE INFORMATION */
/* -------------------------------------------------------------- */
fscanf(infile,"%d\n",&t);					/*  get number of transforms */
if(polar)								/*  .PFS FILE */
{
	for(i = 1 ; i <= t ; i++)		
	{
		fscanf(infile,"%lf %lf %lf %lf %lf %lf %lf\n",
			&xr[i],&ys[i],&thetaangle[i],&phiangle[i],&e[i],&f[i],&p[i]);
		xr[i] *= .01;
		ys[i] *= .01;
		theta[i] = thetaangle[i] * 3.1415926 / 180.;
		phi[i] = phiangle[i] * 3.1415926 / 180.;
		a[i] = xr[i] * cos(theta[i]);					/* convert */
		b[i] = -ys[i] * sin(phi[i]);					/* to */
		c[i] = xr[i] * sin(theta[i]);					/* rectangular */
		d[i] = ys[i] * cos(phi[i]);
		cp[i] = cp[i-1] + p[i-1];				/* fill probability array */
	}
}
else									/* .IFS FILE */
{
	for(i = 1 ; i <= t ; i++)
	{
		fscanf(infile,"%lf %lf %lf %lf %lf %lf %lf\n",
			&a[i],&b[i],&c[i],&d[i],&e[i],&f[i],&p[i]);
		a[i] *= .01;  b[i] *= .01; 				/* adjust to usable form */
		c[i] *= .01;  d[i] *= .01; 
		cp[i] = cp[i-1] + p[i-1];				/* fill probability array */
	}
}
fclose(infile);

/* -------------------------------------------------------------- */
/*	DATA AREA ON VIDEO SCREEN */
/* -------------------------------------------------------------- */
locate(1,1);					
if(showequat)
{
	printf("%d TRANSFORMS IN: %s\n",t,fnam);
	for(i = 1 ; i <= t ; i++)
	{
		if(polar)	
			printf("%.0f %.0f %.0f %.0f %.0f %.0f %.2f\n",
				xr[i]*100,ys[i]*100,thetaangle[i],phiangle[i],e[i],f[i],p[i]);
		else	
			printf("%.0f %.0f %.0f %.0f %.1f %.1f %.2f\n",
				a[i]*100.,b[i]*100.,c[i]*100.,d[i]*100.,e[i],f[i],p[i]);
	}
}

/* -------------------------------------------------------------- */
/*	LAST MINUTE INITIALIZATIONS & 1-TRANSFORM WINDOW SETUP */
/* -------------------------------------------------------------- */
x = 0. ; y = 0. ;				/* initialize x and y */
n = 0;							/* initialize iteration counter */
if(t == 1)						/* 1-transform requires preset window */
{
	minx = miny = -300.;
	maxx = maxy = 300.;
	xrange = maxx - minx;
	yrange = maxy - miny;
	xfactor = 640./xrange;
	yfactor = 225./yrange;
}
else
{
	minx = miny = 1.0E+300; 		/* init. screen limits 		*/
	maxx = maxy = -1.0E+300;		/* for multi-transform sets */
}

/* -------------------------------------------------------------- */
/*	START PROGRAM LOOP */
/* -------------------------------------------------------------- */
do								/* do while user doesn't type 'Q' */
{
	n++;						/* increment iteration counter */
	if(ch)						/* usually just test once, for speed */
	{
		if(ch == 'e')			/* refresh transform display */
		{
			locate(1,1);						
			printf("%d TRANSFORMS IN: %s\n",t,fnam);
			for(i = 1 ; i <= t ; i++)
			{
				if(polar)
					printf("%.0f %.0f %.0f %.0f %.0f %.0f %.2f\n",
						xr[i]*100,ys[i]*100,thetaangle[i],phiangle[i],e[i],f[i],p[i]);
				else
					printf("%.0f %.0f %.0f %.0f %.1f %.1f %.2f\n",
						a[i]*100.,b[i]*100.,c[i]*100.,d[i]*100.,e[i],f[i],p[i]);
			}
		}
		if((ch == 'n') || (ch == 'e'))					/* refresh */
		{												/* point count */
			locate(t+2,1);
			printf("%ld points",n-nonpts);
		}
		if(ch == 'p')						/* .PIC save routine */
		{
			zedsave();						/* save screen */
			rename("SCREEN.ZED",zicnam);	/* rename to proper name */
		}
	}							/* END IF USER TYPED A CHARACTER */

	k = 0;						/* INITIALIZE TRANSFORMATION CHOICE */
	do							/* GENERATE RANDOM NUMBER  > 0.0 */
	{
		r = frand();		
	}
	while(r <= 0.);			

	for(i = 1 ; i <= t ; i++)	/* BUMP TRANSFORMATION CHOICE UP  	*/
		if(r > cp[i])			/* depending on where r falls 		*/
			k += 1;				/* within the possible distribution */
											

	newx = (a[k])*x + (b[k])*y + e[k];		/* CALCULATE NEW POINTS */
	newy = (c[k])*x + (d[k])*y + f[k];

	x = newx ; y = newy;

	if(n <= nonpts)			/* only 1 test most of the time, for speed */
	{
		if(t > 1)				/* if t==1, window is preset earlier */
		{
			if(n <= throwout)		/* just loop if working on throwouts */
				continue;

	if(n < nonpts)			/* tally min and max values seen */
			{
				minx = MIN(minx,x);
				maxx = MAX(maxx,x);
				miny = MIN(miny,y);
				maxy = MAX(maxy,y);
				continue;
			}
	

	if(n == nonpts)			/* compute screen window size */
			{
				xrange = maxx - minx;
				yrange = maxy - miny;

				minx -= (.05 * xrange);		/* add 10% margin */
				maxx += (.05 * xrange);		/* to each axis */
				miny -= (.05 * yrange);
				maxy += (.05 * yrange);

				xrange = maxx - minx;		/* you have to calculate */
				yrange = maxy - miny;		/* the ranges twice!!    */
		

				if((xrange == 0.) || (yrange == 0.))
					abort("\nRange allows division by zero!\n");

				xfactor = 640./xrange;			
				yfactor = 225./yrange;			

				continue;						
			}							/* end if n == nonpts */
		}								/* end if t > 1  */
	}									/* end if n <= nonpts */
	tempx = (int)((x-minx)*xfactor );
	tempy = (int)((y-miny)*yfactor );
	if(upsdwn)							/* invert y axis */
		tempy = 224 - tempy;	

	switch(dispmode)
	{
		case 'm':
			pset(tempx,tempy,4);
			break;

		case 'c':
			pset(tempx,tempy,MIN((point(tempx,tempy)+1),7));
			break;

		case 't':
			pset(tempx,tempy,MIN(k,7));
			break;
	}
}
while((ch = tolower(csts())) != 'q');
puts("\033z");							/* reset terminal */
exit(0);
}

IFS2PFS.C is a program that can (unreliably) translate an IFS set from rectangular to polar notation. 


 

 

Valid HTML 4.01 Transitional
Yahoo! Search
Search the web Search this site
Valid CSS