Path: utzoo!mnetor!uunet!husc6!think!ames!pasteur!ucbvax!SPICE.CS.CMU.EDU!Rick.Busdiecker From: Rick.Busdiecker@SPICE.CS.CMU.EDU Newsgroups: comp.windows.x Subject: Re: Mandelbrot? Message-ID: <578923572.rfb@SPICE.CS.CMU.EDU> Date: 6 May 88 12:06:00 GMT Sender: daemon@ucbvax.BERKELEY.EDU Reply-To: Rick.Busdiecker@cs.cmu.edu Organization: The Internet Lines: 336 Here's the one I use. It's not especially interactive and it's designed for (and so far only been run on) a monochrome screen. It doesn't use the toolkit at all and it breaks a number of ``rules'' for X11 applications. On the brighter side, it let's you spawn off new mandelbrots by typing character's at the window (see server() and spawn()). I've had some problem with the file descriptor for the X server connection which is why spawn uses system() instead of vfork(), but it works so . . . . I'd appreciate getting updates if anyone does any more with this. Rick Busdiecker Expert Technologies, Inc. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Mandelbrot set viewer for the X Window System, Version 11 * * by Rick Busdiecker * * This is PUBLIC DOMAIN software. Do whatever you want with it. * * Try calling with ``-real -0.55 -imag 1.3 -range 2.55 -size 1280 -root'' to fill your root window. */ #include #include #include #include float atof (); void server (); char* getwd (); /* * Global variables */ char* program_name; Display* display; Window root; Window window; GC window_gcontext; Pixmap pixmap; GC pixmap_gcontext; int size = 128; int depth = 20; float real_origin = -2.0; float imaginary_origin = 2.0; float range = 4.0; float contrast_ratio = 0.95; void initialize () { display = XOpenDisplay (NULL); root = XRootWindow (display, XDefaultScreen (display)); } Window initial_window () { Window result; XSetWindowAttributes attributes; XSizeHints hints; char buffer [1024]; attributes.background_pixel = 1; attributes.border_pixel = 0; attributes.event_mask = KeyPressMask; result = XCreateWindow (display, root, 0, 0, size, size, 2, 0, 0, 0, CWBackPixel | CWBorderPixel | CWEventMask, &attributes); hints.flags = PMaxSize | PMinSize; hints.max_width = hints.max_height = hints.min_width = hints.min_height = size; XSetNormalHints (display, result, &hints); XStoreName (display, result, "Mandelbrot"); XSetIconName (display, result, sprintf (buffer, "Mandelbrot: Position = (%g, %g), Range = %g, Depth = %d", real_origin, imaginary_origin, range, depth)); return result; } void initialize_window () { XGCValues values; XMapWindow (display, window); XFlush (display); values.foreground = 0; values.background = 1; window_gcontext = XCreateGC (display, window, GCForeground | GCBackground, &values); } void initialize_bitmap () { XGCValues values; GC temporary_gcontext; pixmap = XCreatePixmap (display, window, size, size, 1); XSetWindowBackgroundPixmap (display, window, pixmap); values.foreground = 0; values.background = 1; pixmap_gcontext = XCreateGC (display, pixmap, GCForeground | GCBackground, &values); values.foreground = 1; temporary_gcontext = XCreateGC (display, pixmap, GCForeground | GCBackground, &values); XFillRectangle (display, pixmap, temporary_gcontext, 0, 0, size, size); XFreeGC (display, temporary_gcontext); } void plot (x, y, bit) int x; int y; int bit; { if (bit) { XDrawPoint (display, window, window_gcontext, x, y); XDrawPoint (display, pixmap, pixmap_gcontext, x, y); } } #define drop_out_distance (4.0) void compute_image () { register int y; for (y = 0; y < size; y++) { register int x; for (x = 0; x < size; x++) { float real_mu = real_origin + (float)x * range / (float)size; float imaginary_mu = imaginary_origin - (float)y * range / (float)size; float real_z = 0.0; float imaginary_z = 0.0; int iteration; for (iteration = 0; iteration < depth; iteration++) { float new_real_z = real_z * real_z - imaginary_z * imaginary_z - real_mu; server (0); imaginary_z = 2 * real_z * imaginary_z - imaginary_mu; real_z = new_real_z; if (real_z * real_z + imaginary_z * imaginary_z >= drop_out_distance) { plot (x, y, ((float)iteration > contrast_ratio * (float)depth) ? 1 : iteration & 1); goto throw; } } throw: /* C doesn't seem to deal well with a label that doesn't have code following it. This ``null statement'' is enough * though. */ ; } } } int match_p (string_1, string_2, minimum) char* string_1; char* string_2; int minimum; { int length_1 = strlen (string_1); int length_2 = strlen (string_2); int short_length = (length_1 < length_2) ? length_1 : length_2; if ((length_1 < minimum) || (length_2 < minimum)) return 0; return !strncmp (string_1, string_2, short_length); } char* next_argument (count, vector) int* count; char*** vector; { if (--*count == 0) { fprintf (stderr, "Missing expected command line argument!\n"); exit (-1); } return *++*vector; } void spawn (real, imaginary, new_range, new_depth, new_size) float real; float imaginary; float new_range; int new_depth; int new_size; { char buffer [2048]; if (! fork ()) { close (3); system (sprintf (buffer, "%s -contrast_ratio %g -depth %d -imaginary_origin %g -size %d -range %g -real_origin %g &", program_name, contrast_ratio, new_depth, imaginary, new_size, new_range, real)); } } void server (block_p) int block_p; { XEvent event; char input = '\0'; if (block_p || XPending (display)) { XNextEvent (display, &event); switch (event.type) { case KeyPress: if (XLookupString (&event, &input, 1, NULL, NULL) == 1) { switch (input) { /* Movement */ case 'u': spawn (real_origin, imaginary_origin + range / 2.0, range, depth, size); break; case 'd': spawn (real_origin, imaginary_origin - range / 2.0, range, depth, size); break; case 'l': spawn (real_origin - range / 2.0, imaginary_origin, range, depth, size); break; case 'r': spawn (real_origin + range / 2.0, imaginary_origin, range, depth, size); break; /* Size */ case 'e': spawn (real_origin, imaginary_origin, range, depth, 2 * size); break; case 's': spawn (real_origin, imaginary_origin, range, depth, size / 2); break; /* Depth */ case 'D': spawn (real_origin, imaginary_origin, range, 2 * depth, size); break; /* Zoom quadrant */ case 'c': spawn (real_origin + range / 4.0, imaginary_origin - range / 4.0, range / 2.0, depth, size); break; case '1': spawn (real_origin + range / 2.0, imaginary_origin, range / 2.0, depth, size); break; case '2': spawn (real_origin, imaginary_origin, range / 2.0, depth, size); break; case '3': spawn (real_origin, imaginary_origin - range / 2.0, range / 2.0, depth, size); break; case '4': spawn (real_origin + range / 2.0, imaginary_origin - range / 2.0, range / 2.0, depth, size); break; /* Quit */ case 'q': XCloseDisplay (display); exit (0); default: ; } } } } } /* * Switches: * [c]ontrast_ratio * [d]epth * [i]maginary_origin * [s]ize * [ra]nge * [re]al_origin * [ro]oot */ int main (argument_count, argument_vector) int argument_count; char** argument_vector; { int root_p = 0; program_name = *argument_vector; while (--argument_count > 0) { char* argument = *++argument_vector; if (*argument == '-') { char* option = argument + 1; if (match_p (option, "contrast_ratio", 1)) contrast_ratio = atof (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "depth", 1)) depth = atoi (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "help", 1)|| match_p (option, "?", 1)) { printf ("%s [-contrast-ratio ] [-depth ] [-help] [-?]\n\ [-imaginary_origin ] [-size ] [-range ]\n\ [-real_origin ] [-root]\n", program_name); exit (0); } else if (match_p (option, "imaginary_origin", 1)) imaginary_origin = atof (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "size", 1)) size = atoi (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "range", 2)) range = atof (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "real_origin", 2)) real_origin = atof (next_argument (&argument_count, &argument_vector)); else if (match_p (option, "root", 2)) root_p = 1; else { fprintf (stderr, "%s: Unknown option ``%s''\n", program_name, option); exit (-1); } } else { fprintf (stderr, "Expecting a command line option but found `%s'.\n", argument); exit (-1); } } initialize (); if (root_p) window = root; else window = initial_window (); initialize_window (); initialize_bitmap (); compute_image (); XClearWindow(display, root); XFlush (display); if (! root_p) while (1) { server (1); } }