Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/freeglut/progs/demos/Fractals/fractals.c @ 3:2c135c81b16c
MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:44:09 +0200 |
| parents | b50eed0cc0ef |
| children |
comparison
equal
deleted
inserted
replaced
| 0:6015a75abc2d | 3:2c135c81b16c |
|---|---|
| 1 /* fractals.c */ | |
| 2 /* | |
| 3 * Program to draw a fractal by Michael Barnsley's deterministic algorithm. | |
| 4 * Algorithm: | |
| 5 * (1) Define the affine transformations (of the form r(i+1) = A r(i) + b ) | |
| 6 * (2) Find the stationary point for each transformation | |
| 7 * (3) To draw: | |
| 8 * - If you are at the lowest level, draw lines connecting all the stationary points | |
| 9 * - If not, call the draw function recursively with each affine transformation applied | |
| 10 */ | |
| 11 | |
| 12 /* | |
| 13 * User Commands: | |
| 14 * +,- - increment/decrement number of levels | |
| 15 * PgUp, PgDn - increase/decrease scaling | |
| 16 * Arrow keys - translate viewing section | |
| 17 * r - reset view | |
| 18 * Escape - quit | |
| 19 */ | |
| 20 | |
| 21 #include <GL/freeglut.h> | |
| 22 #include <stdio.h> | |
| 23 #include <stdlib.h> | |
| 24 #include <string.h> | |
| 25 #include <math.h> | |
| 26 #define FGH_PI 3.14159265358979323846 | |
| 27 | |
| 28 typedef struct | |
| 29 { | |
| 30 double a00, a01, a10, a11 ; /* Transformation matrix */ | |
| 31 double b0, b1 ; /* Constant vector added on */ | |
| 32 double statx, staty ; /* Coordinates of the stationary point */ | |
| 33 } | |
| 34 AffineTrans ; | |
| 35 | |
| 36 /* Number of levels to draw the fractal */ | |
| 37 static int num_levels = 4 ; | |
| 38 | |
| 39 /* The definition of the fractal */ | |
| 40 static int num_trans ; | |
| 41 static AffineTrans *affine ; | |
| 42 | |
| 43 /* Flag telling us to keep executing the main loop */ | |
| 44 static int continue_in_main_loop = 1; | |
| 45 | |
| 46 /* the window title */ | |
| 47 char window_title [ 80 ] ; | |
| 48 | |
| 49 /* The amount the view is translated and scaled */ | |
| 50 double xwin = 0.0, ywin = 0.0 ; | |
| 51 double scale_factor = 1.0 ; | |
| 52 | |
| 53 static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 ) | |
| 54 { | |
| 55 /* Draw a fractal transformed by "M", "N" as passed in */ | |
| 56 int i ; | |
| 57 | |
| 58 if ( num == 0 ) | |
| 59 { | |
| 60 double x0 = m00 * affine[0].statx + m01 * affine[0].staty + n0 ; | |
| 61 double y0 = m10 * affine[0].statx + m11 * affine[0].staty + n1 ; | |
| 62 | |
| 63 for ( i = 1; i < num_trans; i++ ) | |
| 64 { | |
| 65 double x1 = m00 * affine[i].statx + m01 * affine[i].staty + n0 ; | |
| 66 double y1 = m10 * affine[i].statx + m11 * affine[i].staty + n1 ; | |
| 67 | |
| 68 glVertex2d ( x0, y0 ) ; | |
| 69 glVertex2d ( x1, y1 ) ; | |
| 70 | |
| 71 x0 = x1 ; | |
| 72 y0 = y1 ; | |
| 73 } | |
| 74 } | |
| 75 else | |
| 76 { | |
| 77 /* Map each affine transformation in the fractal through the one passed in and call "draw_level" */ | |
| 78 | |
| 79 for ( i = 0; i < num_trans; i++ ) | |
| 80 { | |
| 81 draw_level ( num-1, m00*affine[i].a00+m01*affine[i].a10, m00*affine[i].a01+m01*affine[i].a11, | |
| 82 m10*affine[i].a00+m11*affine[i].a10, m10*affine[i].a01+m11*affine[i].a11, | |
| 83 m00*affine[i].b0 +m01*affine[i].b1 + n0, m10*affine[i].b0 +m11*affine[i].b1 + n1 ) ; | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 static void | |
| 89 Display(void) | |
| 90 { | |
| 91 glClear( GL_COLOR_BUFFER_BIT ); | |
| 92 | |
| 93 /* the curve */ | |
| 94 glPushMatrix(); | |
| 95 glScalef(2.5, 2.5, 2.5); | |
| 96 | |
| 97 glColor4f(0.0, 0.0, 0.0, 1.0); | |
| 98 glBegin ( GL_LINES ) ; | |
| 99 draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ); | |
| 100 glEnd () ; | |
| 101 | |
| 102 glPopMatrix(); | |
| 103 glutSwapBuffers(); | |
| 104 } | |
| 105 | |
| 106 static void | |
| 107 Reshape(int width, int height) | |
| 108 { | |
| 109 float ar; | |
| 110 glViewport ( 0, 0, width, height ) ; | |
| 111 glMatrixMode ( GL_PROJECTION ) ; | |
| 112 glLoadIdentity(); | |
| 113 ar = (float) width / (float) height ; | |
| 114 if( ar > 1 ) | |
| 115 glFrustum ( -ar, ar, -1.0, 1.0, 2.0, 100.0 ) ; | |
| 116 else | |
| 117 glFrustum ( -1.0, 1.0, -1/ar, 1/ar, 2.0, 100.0 ); | |
| 118 glMatrixMode ( GL_MODELVIEW ) ; | |
| 119 glLoadIdentity () ; | |
| 120 xwin = -1.0 ; | |
| 121 ywin = 0.0 ; | |
| 122 glTranslated ( xwin, ywin, -5.0 ) ; | |
| 123 } | |
| 124 | |
| 125 static void | |
| 126 Key(unsigned char key, int x, int y) | |
| 127 { | |
| 128 int need_redisplay = 1; | |
| 129 | |
| 130 switch (key) { | |
| 131 case 27: /* Escape key */ | |
| 132 continue_in_main_loop = 0 ; | |
| 133 break; | |
| 134 | |
| 135 case '+' : | |
| 136 ++num_levels ; | |
| 137 break ; | |
| 138 | |
| 139 case '-' : | |
| 140 if ( num_levels > 0 ) | |
| 141 --num_levels ; | |
| 142 break ; | |
| 143 | |
| 144 case 'r' : case 'R' : | |
| 145 glMatrixMode ( GL_MODELVIEW ) ; | |
| 146 glLoadIdentity(); | |
| 147 xwin = -1.0 ; | |
| 148 ywin = 0.0 ; | |
| 149 glTranslated ( xwin, ywin, -5.0 ) ; | |
| 150 break ; | |
| 151 | |
| 152 default: | |
| 153 need_redisplay = 0; | |
| 154 break; | |
| 155 } | |
| 156 if (need_redisplay) | |
| 157 glutPostRedisplay(); | |
| 158 } | |
| 159 | |
| 160 static void | |
| 161 Special(int key, int x, int y) | |
| 162 { | |
| 163 int need_redisplay = 1; | |
| 164 | |
| 165 switch (key) { | |
| 166 case GLUT_KEY_UP : | |
| 167 glMatrixMode ( GL_MODELVIEW ) ; | |
| 168 ywin += 0.1 * scale_factor ; | |
| 169 glTranslated ( 0.0, 0.1 * scale_factor, 0.0 ) ; | |
| 170 break ; | |
| 171 | |
| 172 case GLUT_KEY_DOWN : | |
| 173 glMatrixMode ( GL_MODELVIEW ) ; | |
| 174 ywin -= 0.1 * scale_factor ; | |
| 175 glTranslated ( 0.0, -0.1 * scale_factor, 0.0 ) ; | |
| 176 break ; | |
| 177 | |
| 178 case GLUT_KEY_LEFT : | |
| 179 glMatrixMode ( GL_MODELVIEW ) ; | |
| 180 xwin -= 0.1 * scale_factor ; | |
| 181 glTranslated ( -0.1 * scale_factor, 0.0, 0.0 ) ; | |
| 182 break ; | |
| 183 | |
| 184 case GLUT_KEY_RIGHT : | |
| 185 glMatrixMode ( GL_MODELVIEW ) ; | |
| 186 xwin += 0.1 * scale_factor ; | |
| 187 glTranslated ( 0.1 * scale_factor, 0.0, 0.0 ) ; | |
| 188 break ; | |
| 189 | |
| 190 case GLUT_KEY_PAGE_UP : | |
| 191 glMatrixMode ( GL_MODELVIEW ) ; | |
| 192 glTranslated ( -xwin, -ywin, 0.0 ) ; | |
| 193 glScaled ( 1.25, 1.25, 1.25 ) ; | |
| 194 glTranslated ( xwin, ywin, 0.0 ) ; | |
| 195 scale_factor *= 0.8 ; | |
| 196 break ; | |
| 197 | |
| 198 case GLUT_KEY_PAGE_DOWN : | |
| 199 glMatrixMode ( GL_MODELVIEW ) ; | |
| 200 glTranslated ( -xwin, -ywin, 0.0 ) ; | |
| 201 glScaled ( 0.8, 0.8, 0.8 ) ; | |
| 202 glTranslated ( xwin, ywin, 0.0 ) ; | |
| 203 scale_factor *= 1.25 ; | |
| 204 break ; | |
| 205 | |
| 206 default: | |
| 207 need_redisplay = 0; | |
| 208 break; | |
| 209 } | |
| 210 if (need_redisplay) | |
| 211 glutPostRedisplay(); | |
| 212 } | |
| 213 | |
| 214 | |
| 215 static void | |
| 216 checkedFGets ( char *s, int size, FILE *stream ) | |
| 217 { | |
| 218 if ( fgets ( s, size, stream ) == NULL ) { | |
| 219 fprintf ( stderr, "fgets failed\n"); | |
| 220 exit ( EXIT_FAILURE ); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 | |
| 225 void readConfigFile ( char *fnme ) | |
| 226 { | |
| 227 FILE *fptr = fopen ( fnme, "rt" ) ; | |
| 228 int i ; | |
| 229 char inputline [ 256 ] ; | |
| 230 | |
| 231 if ( fptr ) | |
| 232 { | |
| 233 /* Read a header line */ | |
| 234 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 235 | |
| 236 /* Read a comment line */ | |
| 237 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 238 | |
| 239 /* Read the window title */ | |
| 240 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 241 /* We assume here that this line will not exceed 79 characters plus a | |
| 242 newline (window_title is 80 characters long). That'll cause a buffer | |
| 243 overflow. For a simple program like this, though, we're letting it | |
| 244 slide! | |
| 245 */ | |
| 246 sscanf ( inputline, "%[a-zA-Z0-9!@#$%^&*()+=/\\_-\" ]", window_title ) ; | |
| 247 | |
| 248 /* Read a comment line */ | |
| 249 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 250 | |
| 251 /* Read the number of affine transformations */ | |
| 252 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 253 sscanf ( inputline, "%d", &num_trans ) ; | |
| 254 | |
| 255 affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; | |
| 256 | |
| 257 /* Read a comment line */ | |
| 258 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 259 | |
| 260 for ( i = 0; i < num_trans; i++ ) | |
| 261 { | |
| 262 /* Read an affine transformation definition */ | |
| 263 checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; | |
| 264 sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01, | |
| 265 &affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ; | |
| 266 } | |
| 267 } | |
| 268 else /* No data file, set a default */ | |
| 269 { | |
| 270 printf ( "ERROR opening file <%s>\n", fnme ) ; | |
| 271 strcpy ( window_title, "Koch Snowflake" ) ; | |
| 272 num_trans = 4 ; | |
| 273 affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; | |
| 274 affine[0].a00 = 1/3. ; affine[0].a01 = 0.00 ; affine[0].a10 = 0.00 ; affine[0].a11 = 1/3. ; | |
| 275 affine[0].b0 = 0.0 ; affine[0].b1 = 0.0 ; | |
| 276 | |
| 277 affine[1].a00 = 1/6. ; affine[1].a01 = -1/3.*sin(FGH_PI/3.) ; affine[1].a10 = 1/3.*sin(FGH_PI/3.) ; affine[1].a11 = 1/6. ; | |
| 278 affine[1].b0 = 1/3. ; affine[1].b1 = 0.0 ; | |
| 279 | |
| 280 affine[2].a00 = 1/6. ; affine[2].a01 = -1/3.*sin(-FGH_PI/3.) ; affine[2].a10 = 1/3.*sin(-FGH_PI/3.) ; affine[2].a11 = 1/6. ; | |
| 281 affine[2].b0 = 0.5 ; affine[2].b1 = sqrt(3)/6. ; | |
| 282 | |
| 283 affine[3].a00 = 1/3. ; affine[3].a01 = 0.00 ; affine[3].a10 = 0.00 ; affine[3].a11 = 1/3. ; | |
| 284 affine[3].b0 = 2/3. ; affine[3].b1 = 0.0 ; | |
| 285 } | |
| 286 | |
| 287 for ( i = 0; i < num_trans; i++ ) | |
| 288 { | |
| 289 double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */ | |
| 290 double determ ; /* Determinant of this matrix */ | |
| 291 | |
| 292 /* Calculate the stationary point */ | |
| 293 | |
| 294 m00 = 1.0 - affine[i].a00 ; | |
| 295 m01 = - affine[i].a01 ; | |
| 296 m10 = - affine[i].a10 ; | |
| 297 m11 = 1.0 - affine[i].a11 ; | |
| 298 | |
| 299 determ = m00 * m11 - m01 * m10 ; | |
| 300 | |
| 301 if ( fabs ( determ ) > 1.e-6 ) | |
| 302 { | |
| 303 affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ; | |
| 304 affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ; | |
| 305 } | |
| 306 else | |
| 307 affine[i].statx = affine[i].staty = 0.0 ; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 int | |
| 312 main(int argc, char *argv[]) | |
| 313 { | |
| 314 glutInitWindowSize(500, 250); | |
| 315 glutInitWindowPosition ( 140, 140 ); | |
| 316 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE ); | |
| 317 glutInit(&argc, argv); | |
| 318 | |
| 319 if ( argc > 1 ) | |
| 320 readConfigFile ( argv[1] ) ; | |
| 321 else | |
| 322 readConfigFile ( "fractals.dat" ) ; | |
| 323 | |
| 324 glutCreateWindow( window_title ); | |
| 325 | |
| 326 glClearColor(1.0, 1.0, 1.0, 1.0); | |
| 327 | |
| 328 glutReshapeFunc(Reshape); | |
| 329 glutKeyboardFunc(Key); | |
| 330 glutSpecialFunc(Special); | |
| 331 glutDisplayFunc(Display); | |
| 332 | |
| 333 #ifdef WIN32 | |
| 334 #endif | |
| 335 | |
| 336 while ( continue_in_main_loop ) | |
| 337 glutMainLoopEvent(); | |
| 338 | |
| 339 printf ( "Back from the 'freeglut' main loop\n" ) ; | |
| 340 | |
| 341 return 0; /* ANSI C requires main to return int. */ | |
| 342 } |
