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 }