A Sample X Program
/* xifs */
/* by Thomas Colthurst. Version 1.0. Started April 7, 1990. */
/* Displays the IFS attractor whose codes are stored in a file of the following format:
numpixels
xsize ysize
xposition yposition
numtransformations
p1 a1 b1 c1 d1 e1 f1
...
pn an bn cn dn en fn
where size and position are based upon a window size of [500 x 500],
p is the probability of the transformation,
and a .. f determine the transformation
x = [ a b ] x + [ e ]
[ c d ] [ f ]
At present, numpixels is not supported and the image will be generated until the
program stops. The program can be stopped by pressing a mouse button in the
window or by typing a 'q' in the window. The image can be saved by typing a 's'
in the window, and then entering a filename.
*/
/* External functions and information */
#include
#include
#include
#include
long random();
/* Global functions and variables */
#define irint(x) ( (int) rint(x) )
typedef struct {
double x, y;
} point;
char xifs[] = "tc's xifs";
point nextpoint();
/* X variables */
Display *mydisplay;
Window mywindow;
GC mygc;
XEvent myevent;
KeySym mykey;
XSizeHints myhint;
XSetWindowAttributes my_window_attributes;
int myscreen;
unsigned long myforeground, mybackground;
unsigned long my_win_values_mask;
/* file IFS information */
typedef struct {
int stop;
double xsize, ysize;
double x0, y0;
int wnum;
double w[1000][7];
} IFS;
IFS theifs;
/* Function Declarations */
void readifs( char *fname, IFS *theifs );
void openifswindow ( int height, int width, char **argv, int argc );
point nextpoint ( point old, IFS *theifs );
void closeifswindow();
/* The Program */
int main(int argc,char **argv)
{
char fname[128];
int count, start;
point pt;
int height, width;
char text[10];
int k, i;
int done;
double maxx, maxy, minx, miny;
/* Read in IFS codes from a file */
if ( argc == 1 ) {
printf ( "Enter filename: " );
scanf ( "%s", fname );
}
else {
strcpy ( fname, argv[1] );
}
readifs ( fname, &theifs );
/* Set up window info */
height = 500; width = 500;
openifswindow ( height, width, argc, argv );
/* Initialize ifs variables */
start = 25;
count = 0;
pt.x = 0.5; pt.y = 0.5;
/* Main Event Loop */
done = 0;
while ( done == 0 ) {
while ( ( XEventsQueued ( mydisplay, QueuedAfterReading ) == 0 )
/* && ( count < theifs.stop ) */ )
{
/* Get next IFS Point */
pt = nextpoint ( pt, &theifs );
/* Draw it */
if ( count++ > start )
XDrawPoint ( mydisplay, mywindow, mygc,
irint( ( pt.x*theifs.xsize + theifs.x0)*width ),
irint( ( pt.y*theifs.ysize + theifs.y0)*height ) );
XFlush ( mydisplay );
}
XNextEvent ( mydisplay, &myevent );
switch ( myevent.type ) {
case Expose:
if ( myevent.xexpose.count == 0 )
{ };
break;
case MappingNotify:
XRefreshKeyboardMapping ( &myevent );
break;
case ButtonPress:
done = 1;
break;
case KeyPress:
i = XLookupString ( &myevent, text, 10, &myevent, 0 );
if ( i == 1 && text[0] == 'q' ) done = 1;
else if ( i ==1 && text[0] == 's' ) {
printf ( "Enter filename for bitmap: " );
scanf ( "%s", fname );
XWriteBitmapFile ( mydisplay, fname, mywindow, width, height, -1, -1 );
printf ( "%s saved.\n", fname );
}
else if ( i == 1 && text[0] == 'p ) {
printf( "Current point is (%f, %f)\n", pt.x, pt.y );
}
else
printf ( "Type q to quit, s to save.\n" );
break;
case ConfigureNotify:
if ( ( height != myevent.xconfigure.height ) ||
( width != myevent.xconfigure.width ) ) {
height = myevent.xconfigure.height;
width = myevent.xconfigure.width;
count = 0;
XClearArea ( mydisplay, mywindow, 0, 0, height, width, 0 );
}
break;
} /* switch ( myevent.type ) */
} /* while ( done == 0 ) */
/* Bye, bye */
closeifswindow();
exit ( 0 );
} /* main */
void readifs( char *fname, IFS *theifs )
/* Read in ifs code from file with name fname into theifs */
{
FILE *ifsfile;
int i;
ifsfile = fopen ( fname, "r" );
/* printf ( "%s opened ... \n", fname ); */
fscanf ( ifsfile, "%d", &theifs->stop );
fscanf ( ifsfile, "%lf%lf", &theifs->xsize, &theifs->ysize );
fscanf ( ifsfile, "%lf%lf", &theifs->x0, &theifs->y0 );
fscanf ( ifsfile, "%d", &theifs->wnum );
for ( i = 0; i < theifs->wnum; i++ ) {
fscanf ( ifsfile, "%lf %lf %lf %lf %lf %lf %lf",
&theifs->w[i][0],
&theifs->w[i][1], &theifs->w[i][2],
&theifs->w[i][3], &theifs->w[i][4],
&theifs->w[i][5], &theifs->w[i][6] );
}
/* printf ( "Done reading.\n" ); */
fclose ( ifsfile );
}
void openifswindow ( int height, int width, char **argv, int argc )
{
/* Set up display */
mydisplay = XOpenDisplay("");
myscreen = DefaultScreen ( mydisplay );
mybackground = WhitePixel ( mydisplay, myscreen );
myforeground = BlackPixel ( mydisplay, myscreen );
myhint.x = 200; myhint.y = 300;
myhint.width = width; myhint.height = height;
myhint.flags = PPosition | PSize;
/* Create Window */
mywindow = XCreateSimpleWindow ( mydisplay,
DefaultRootWindow ( mydisplay ),
myhint.x, myhint.y, myhint.width, myhint.height,
5, myforeground, mybackground );
XSetStandardProperties ( mydisplay, mywindow, xifs, xifs,
None, argv, argc, &myhint );
/* Create Graphic Context */
mygc = XCreateGC ( mydisplay, mywindow, 0, 0 );
XSetBackground ( mydisplay, mygc, mybackground );
XSetForeground ( mydisplay, mygc, myforeground );
/* Solicit press and exposure events */
XSelectInput ( mydisplay, mywindow,
ButtonPressMask | KeyPressMask | ExposureMask | StructureNotifyMask );
/* Map window */
XMapRaised ( mydisplay, mywindow );
/* Set backing store */
my_window_attributes.backing_store = Always;
XChangeWindowAttributes ( mydisplay, mywindow, CWBackingStore,
&my_window_attributes );
while ( XCheckWindowEvent( mydisplay, mywindow, ExposureMask, &myevent ) == 0 )
;
}
point nextpoint ( point old, IFS *theifs )
{
point new;
double prob;
int k;
/* Generate random number between 0 and 1 */
prob = fmod ( (double) random() / 32768.0, 1.0 );
/* Find transformation based upon probabilites and prob */
k = 0; while ( prob > theifs->w[k][0] ) k++;
/* Generate new point */
new.x = theifs->w [ k][ 1 ] * old.x + theifs->w [ k][ 2 ] * old.y + theifs->w [ k][ 5 ];
new.y = theifs->w [ k][ 3 ] * old.x + theifs->w [ k][ 4 ] * old.y + theifs->w [ k][ 6 ];
return new;
}
void closeifswindow()
{
XFreeGC ( mydisplay, mygc );
XDestroyWindow ( mydisplay, mywindow );
XCloseDisplay ( mydisplay );
}