Path: utzoo!mnetor!uunet!lll-winken!lll-tis!mordor!sri-spam!ames!pasteur!ucbvax!decwrl!nsc!daisy!turner
From: turner@daisy.UUCP (D'arc Angel)
Newsgroups: comp.windows.x
Subject: Re: Mandelbrot?
Message-ID: <1132@daisy.UUCP>
Date: 10 May 88 13:30:12 GMT
References: <16823@cornell.UUCP>
Reply-To: turner@daisy.UUCP (D'arc Angel)
Distribution: comp
Organization: The Houses of the Holy
Lines: 342


I don't know how good this is.....

#define DEBUG 0

#include 
#include 
#include 


#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