jrr@arvak.cs.cornell.edu (Jim Russell) (05/06/88)
Does anybody out there have a good mandelbrot program for X10 or X11? If possible, interactive, mouse-driven, etc, with source code, preferably written in C? Thanks in advance, --chet-- murthy@svax.cs.cornell.edu
Rick.Busdiecker@SPICE.CS.CMU.EDU (05/06/88)
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 <stdio.h> #include <sys/param.h> #include <X11/Xlib.h> #include <X11/Xutil.h> 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 <float>] [-depth <integer>] [-help] [-?]\n\ [-imaginary_origin <float>] [-size <integer>] [-range <float>]\n\ [-real_origin <float>] [-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); } }
turner@daisy.UUCP (D'arc Angel) (05/10/88)
I don't know how good this is..... #define DEBUG 0 #include <stdio.h> #include <X11/Xlib.h> #include <X11/X.h> #define MAX_COLORS 6 Display *display; Window window; int screen; extern int optind; extern char *optarg, getopt(); int cycling; main (argc, argv) int argc; char *argv[]; { int colors[MAX_COLORS+1]; int ncolors; int width; int height; window = winit (argc, argv, &width, &height); XSync(display, DEBUG); ncolors = set_colors (colors); make_fractal (window, width, height, colors, ncolors); if(cycling) cycle_colors (colors, ncolors); pause (); uninit (window); exit (0); } winit (argc, argv, width, height) int argc; char *argv[]; int *width; int *height; { XWindowAttributes window_attr; int i; char *hostname = NULL; char *geometry = NULL; int geomx, geomy, geomw, geomh; char c; geomx = 0; geomy = 0; geomw = 256; geomh = 256; /* defaults */ cycling = 1; while ((c = getopt(argc, argv, "g:d:c")) != EOF) switch (c) { case 'g': geometry = optarg; XParseGeometry(geometry, &geomx, &geomy, &geomw, &geomh); break; case 'd': hostname = optarg; break; case 'c': /* turn off cycling */ cycling = 0; break; default: usage(); } if ((display = XOpenDisplay (hostname)) == NULL) { printf ("%s: Unable to connect to display.\n", argv[0]); exit (1); } screen = DefaultScreen(display); if ((window = XCreateSimpleWindow (display, RootWindow(display, screen), geomx, geomy, geomw, geomh, 5, BlackPixel(display, screen), WhitePixel(display, screen))) == NULL) { printf ("%s: Unable to create window.\n", argv[0]); exit (1); } XGetWindowAttributes(display, window, &window_attr); *width = window_attr.width; *height = window_attr.height; return (window); } int set_colors (colors) int colors[]; { static char *name[] = {"Red", "Yellow", "Green", "Cyan", "Blue", "Magenta", "Black"}; XColor hw_def; XColor exact_def; Colormap cmap; int ncolors; int planes; int i; cmap = DefaultColormap(display, 0); for (ncolors = 6; ncolors >= 0; ncolors--) if (XAllocColorCells (display, cmap, 0, &planes, 0, colors, ncolors+1)) break; name[ncolors] = name[6]; for (i = 0; i <= ncolors; i++) { XAllocNamedColor (display, cmap, name[i], &hw_def, &exact_def); exact_def.pixel = colors[i]; XStoreColors (display, cmap, &exact_def, 1); } return (ncolors); } cycle_colors (colors, ncolors) int colors[]; int ncolors; { static char *name[] = {"Red", "Yellow", "Green", "Cyan", "Blue", "Magenta"}; XColor hw_def; XColor exact_def[6]; Colormap cmap; int ist; int i; cmap = DefaultColormap(display, 0); for (i = 0; i < ncolors; i++) XAllocNamedColor (display, cmap, name[i], &hw_def, &exact_def[i]); for (ist = 0; ; ist = (ist + ncolors - 1) % ncolors) { for (i = 0; i < ncolors; i++) { exact_def[i].pixel = colors[(ist + i) % ncolors]; XStoreColors (display, cmap, &exact_def[i], 1); } } } make_fractal (window, max_pixels_x, max_pixels_y, colors, ncolors) Window window; int max_pixels_x; int max_pixels_y; int *colors; int ncolors; { static GC gc = NULL; XGCValues values; unsigned long valuemask; register int ix; register int iy; register int i; register double x; register double y; register double yl; register double x2; register double y2; static int max_iterations = 1000; static double max_value = 10.0; static double xcenter = 0.0; static double ycenter = 0.0; static double width = 2.0; static double height = 2.4; static double p = 0.32; static double q = 0.043; double min_x; double max_x; double min_y; double max_y; double pixwd; double pixht; int rows; int iclr; int mirror; if ((width / (double) max_pixels_x) > (height / (double) max_pixels_y)) height = width * ((double) max_pixels_y / (double) max_pixels_x); else width = height * ((double) max_pixels_x / (double) max_pixels_y); check_values (&max_iterations, &xcenter, &ycenter, &width, &height, &max_value, &p, &q); mirror = ((xcenter == 0.0) && (ycenter == 0.0)); if ((width / (double) max_pixels_x) > (height / (double) max_pixels_y)) height = width * ((double) max_pixels_y / (double) max_pixels_x); else width = height * ((double) max_pixels_x / (double) max_pixels_y); max_x = xcenter + width / 2.0; min_x = xcenter - width / 2.0; max_y = ycenter + height / 2.0; min_y = ycenter - height / 2.0; rows = (mirror ? (max_pixels_y + 1) / 2 : max_pixels_y); pixwd = (max_x - min_x) / ((double) (max_pixels_x-1)); pixht = (max_y - min_y) / ((double) (max_pixels_y-1)); XMapWindow (display, window); for (iy = 0; iy < rows; iy++) { yl = pixht * (double) iy + min_y; for (ix = 0; ix < max_pixels_x; ix++) { x = pixwd * (double) ix + min_x; y = yl; for (i = 0; i < max_iterations; i++) { x2 = x * x; y2 = y * y; if (x2 + y2 > max_value) break; y = ((double) 2.0) * x * y + q; x = x2 - y2 + p; } iclr = ((i < max_iterations) ? i % ncolors : ncolors); if(gc == NULL) gc = XCreateGC(display, window, 0, &values); XSetFillStyle(display, gc, FillSolid); XSetForeground(display, gc, colors[iclr]); XFillRectangle(display, window, gc, ix, max_pixels_y-iy-1, 1, 1); if (mirror) XFillRectangle(display, window, gc, max_pixels_x-ix-1, iy, 1, 1); } } } uninit (window) Window window; { XUnmapWindow (window); } check_values (max_iterations, xcenter, ycenter, width, height, max_value, p, q) int *max_iterations; double *xcenter; double *ycenter; double *width; double *height; double *max_value; double *p; double *q; { static struct {char *desc; char *fmt; char *addr;} pardef[] = {{"Maximum iterations:", "%d", (char *) 0}, {"Maximum value: ", "%lf", (char *) 0}, {"X Center: ", "%lf", (char *) 0}, {"Y Center: ", "%lf", (char *) 0}, {"Width: ", "%lf", (char *) 0}, {"Height: ", "%lf", (char *) 0}, {"P: ", "%lf", (char *) 0}, {"Q: ", "%lf", (char *) 0}}; int field; int ndx; int end; char resp[256]; char format[256]; pardef[0].addr = (char *) max_iterations; pardef[1].addr = (char *) max_value; pardef[2].addr = (char *) xcenter; pardef[3].addr = (char *) ycenter; pardef[4].addr = (char *) width; pardef[5].addr = (char *) height; pardef[6].addr = (char *) p; pardef[7].addr = (char *) q; do { printf ("\n\n"); for (ndx = 0; ndx < sizeof (pardef) / sizeof (*pardef); ndx++) { sprintf (format, "%4d. %s %s \n", ndx + 1, pardef[ndx].desc, pardef[ndx].fmt); if (!strcmp (pardef[ndx].fmt, "%lf")) printf (format, *((double *) pardef[ndx].addr)); else if (!strcmp (pardef[ndx].fmt, "%d")) printf (format, *((int *) pardef[ndx].addr)); else if (!strcmp (pardef[ndx].fmt, "%s")) printf (format, (char *) pardef[ndx].addr); } printf ("\n\nWhat do you want to change: "); end = !gets (resp); if (!end) end = !*resp; if (!end) { sscanf (resp, "%d", &field); if ((field > 0) && (field <= sizeof (pardef) / sizeof (*pardef))) { field--; printf ("\n\n%s ", pardef[field].desc); if (gets (resp)) sscanf (resp, pardef[field].fmt, pardef[field].addr); } } } while (!end); } usage() { fprintf(stderr, "Usage is:\n"); fprintf(stderr, "\tXFractal [-d displayname] [-g geometry] [-c] [-h]\n"); fprintf(stderr, "Where:\n"); fprintf(stderr, "-c\t\tdo not cycle colors when done drawing\n"); fprintf(stderr, "-h\t\ttype this message\n"); fprintf(stderr, "\n"); fprintf(stderr, "Note: to turn off the mirroring of the image around the X \n"); fprintf(stderr, "\taxis, select a center (items 3 and 4) other than 0,0\n"); exit(1); } -- Laissez les bons temps rouler - Queen Ida ...{decwrl|ucbvax}!imagen!atari!daisy!turner (James M. Turner) Daisy Systems, 700 E. Middlefield Rd, P.O. Box 7006, Mountain View CA 94039-7006. (415)960-0123
mao@blipyramid.BLI.COM (Mike Olson) (05/12/88)
turner's mandelbrot set plotter for color workstations is nice. i fixed one bug in the set_colors() routine. the code had assumed that you were on screen 0 of your display. in the case of color sun workstations, this isn't true. both the monochrome and color screens are available, and are numbered, respectively, 0 and 1. context diff follows. 'man2.c' is the version i pulled off the net. 'man3.c' is the fixed version. mike olson britton lee, inc. ...!ucbvax!mtxinu!blia!mao olson@ucbvax.berkeley.edu *** man2.c Wed May 11 09:53:04 1988 --- man3.c Wed May 11 10:40:16 1988 *************** *** 128,134 int planes; int i; ! cmap = DefaultColormap(display, 0); for (ncolors = 6; ncolors >= 0; ncolors--) if (XAllocColorCells (display, cmap, 0, &planes, 0, colors, ncolors+1)) --- 128,134 ----- int planes; int i; ! cmap = DefaultColormap(display, DefaultScreen(display)); for (ncolors = 6; ncolors >= 0; ncolors--) if (XAllocColorCells (display, cmap, 0, &planes, 0, colors, ncolors+1))