Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

fractals.c

00001 /* Fractal Example on 128x64 display
00002    Copyright (C) 2003 Free Software Foundation, Inc.
00003    Written by Stephane Carrez (stcarrez@nerim.fr)       
00004 
00005 This file is free software; you can redistribute it and/or modify it
00006 under the terms of the GNU General Public License as published by the
00007 Free Software Foundation; either version 2, or (at your option) any
00008 later version.
00009 
00010 In addition to the permissions in the GNU General Public License, the
00011 Free Software Foundation gives you unlimited permission to link the
00012 compiled version of this file with other programs, and to distribute
00013 those programs without any restriction coming from the use of this
00014 file.  (The General Public License restrictions do apply in other
00015 respects; for example, they cover modification of the file, and
00016 distribution when not linked into another program.)
00017 
00018 This file is distributed in the hope that it will be useful, but
00019 WITHOUT ANY WARRANTY; without even the implied warranty of
00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021 General Public License for more details.
00022 
00023 You should have received a copy of the GNU General Public License
00024 along with this program; see the file COPYING.  If not, write to
00025 the Free Software Foundation, 59 Temple Place - Suite 330,
00026 Boston, MA 02111-1307, USA.  */
00027 
00038 #include <gdm/display.h>
00039 #include <stdlib.h>
00040 
00041 gdm_display display;
00042 
00043 static void
00044 fractal_line (short x1, short y1, short x2, short y2, short recurse)
00045 {
00046   if (x1 == x2 && y1 == y2)
00047     {
00048       gdm_draw_point (&display, x1, y1);
00049     }
00050   else if (recurse <= 0)
00051     {
00052       gdm_draw_line (&display, x1, y1, x2, y2);
00053     }
00054   else
00055     {
00056       short x, y, x3, y3, x4, y4;
00057       short dx = (x2 - x1) / 3;
00058       short dy = (y2 - y1) / 3;
00059 
00060       recurse--;
00061       x = x1 + dx;
00062       y = y1 + dy;
00063       fractal_line (x1, y1, x, y, recurse);
00064 
00065       x3 = x - dy;
00066       y3 = y + dx;
00067       fractal_line (x, y, x3, y3, recurse);
00068 
00069       x = x2 - dx;
00070       y = y2 - dy;
00071       fractal_line (x, y, x2, y2, recurse);
00072 
00073       x4 = x - dy;
00074       y4 = y + dx;
00075       fractal_line (x3, y3, x4, y4, recurse);
00076 
00077       fractal_line (x4, y4, x, y, recurse);
00078     }
00079 }
00080 
00081 #define MAXIT 14
00082 #define BASE (8192)
00083 #define F(VAL) ((long) ((VAL) * (double) BASE))
00084 #define PHYSX(VAL) ((short) ((128 * ((VAL) - F(-5.0))) / ((F(5.0) - F(-5.0)))))
00085 #define PHYSY(VAL) ((short) ((64 * ((VAL) - F(0.0))) / ((F(10.0) - F(0.0)))))
00086 
00087 void
00088 fern ()
00089 {
00090   int j;
00091 
00092   for (j = 0; j < 1000; j++)
00093     {
00094       int i;
00095       
00096       // Temporary x and y values during iterations.
00097       long  newx;
00098       long  newy;
00099 
00100       // Get initial x and y values, both between 0 and 1.
00101       long x = (long) (((unsigned short) rand ()) % (unsigned short) BASE);
00102       long y = (long) (((unsigned short) rand ()) % (unsigned short) BASE);
00103 
00104       gdm_refresh (&display);
00105       for (i = 0; i < MAXIT; i++)
00106         {
00107           unsigned long  rand_num = ((unsigned short) rand()) % BASE;
00108 
00109           if (rand_num < F(0.01))
00110             {
00111               newx = F(0.0);
00112               newy = (F(0.16) * y) / BASE;
00113               x = newx;
00114               y = newy;
00115             }  // rand_num < 0.01
00116           else
00117             if (rand_num < F(0.86))
00118               {
00119                 newx = ((F(0.85) * x) + (F(0.04) * y)) / BASE;
00120                 newy = ((-F(0.04) * x) + (F(0.85) * y)) / BASE + F(1.6);
00121                 x = newx;
00122                 y = newy;
00123               }  // (rand_num < 0.86)
00124             else
00125               if (rand_num < F(0.93))
00126                 {
00127                   newx = ((F(0.2) * x) - (F(0.26) * y)) / BASE;
00128                   newy = ((F(0.23) * x) + (F(0.22) * y)) / BASE + F(1.6);
00129                   x = newx;
00130                   y = newy;
00131                 }  // (rand_num < 0.93)
00132               else
00133                 {
00134                   newx = ((F(-0.15) * x) + (F(0.28) * y)) / BASE;
00135                   newy = ((F(0.26) * x) + (F(0.24) * y)) / BASE + F(0.44);
00136                   x = newx;
00137                   y = newy;
00138                 }  // (rand_num >= 0.93)
00139         }  // for (int i = 0; i < MAXIT; i++)
00140 
00141       gdm_draw_point (&display, PHYSX(x), PHYSY(y));
00142     }
00143 }
00144 
00145 static const gdm_point pts[] = {
00146   { 128, 62 }, { 0, 62},
00147   { 64, 0}, { 64, 64 },
00148   { 64, 64}, { 64, 0 },
00149   { 0, 0}, { 64, 64 },
00150   { 64, 64}, { 0, 0 },
00151   { 128, 64}, { 0, 0 },
00152   { 0, 0}, { 128, 64 }
00153 };
00154 
00155 int
00156 main ()
00157 {
00158   short dt = 1;
00159   short recurse = 0;
00160   short orecurse = 0;
00161   int i = 0;
00162 
00163   gdm_initialize (&display);
00164 
00165   while (1)
00166     {
00167       /* First erase the previous fractal.  */
00168       gdm_set_gc (&display, GDM_PLOT_AND);
00169       gdm_fill_rectangle (&display, 0, 0, GDM_WIDTH, GDM_HEIGHT);
00170 
00171       /* Draw the new fractal in OR mode because we can touch the
00172          same pixel several times (due to rounding).  */
00173       gdm_set_gc (&display, GDM_PLOT_OR);
00174       fractal_line (pts[i].x, pts[i].y, pts[i+1].x, pts[i+1].y, recurse);
00175 
00176       /* Change fractal recursion.  */
00177       orecurse = recurse;
00178       recurse += dt;
00179       if (recurse > 4)
00180         {
00181           dt = -1;
00182         }
00183       else if (recurse < 0)
00184         {
00185           dt = 1;
00186           i += 2;
00187           if (i >= sizeof(pts) / sizeof(pts[0]))
00188             i = 0;
00189 
00190           gdm_set_gc (&display, GDM_PLOT_AND);
00191           gdm_fill_rectangle (&display, 0, 0, GDM_WIDTH, GDM_HEIGHT);
00192 
00193           gdm_set_gc (&display, GDM_PLOT_OR);
00194           fern ();
00195         }
00196 
00197       gdm_refresh (&display);
00198     }
00199 }