00001
00002
00003
00004 #if !defined( lint ) && !defined( SABER )
00005 static const char sccsid[] = "@(#)ifs.c 5.00 2002/04/11 baffe";
00006 #endif
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <math.h>
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #include "ifs.h"
00043
00044 #define MODE_ifs
00045
00046 #define PROGCLASS "IFS"
00047
00048 #define HACK_INIT init_ifs
00049 #define HACK_DRAW draw_ifs
00050
00051 #define ifs_opts xlockmore_opts
00052
00053 #define DEFAULTS "*delay: 20000 \n" \
00054 "*ncolors: 100 \n"
00055
00056 #define SMOOTH_COLORS
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include "goom_tools.h"
00078
00079 #define LRAND() ((long) (RAND() & 0x7fffffff))
00080 #define NRAND(n) ((int) (LRAND() % (n)))
00081 #define MAXRAND (2147483648.0)
00082
00083
00084
00085
00086 typedef float DBL;
00087 typedef int F_PT;
00088
00089
00090
00091
00092
00093 #define FIX 12
00094 #define UNIT ( 1<<FIX )
00095 #define MAX_SIMI 6
00096
00097 #define MAX_DEPTH_2 10
00098 #define MAX_DEPTH_3 6
00099 #define MAX_DEPTH_4 4
00100 #define MAX_DEPTH_5 2
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #define DBL_To_F_PT(x) (F_PT)( (DBL)(UNIT)*(x) )
00113
00114 typedef struct Similitude_Struct SIMI;
00115 typedef struct Fractal_Struct FRACTAL;
00116
00117 struct Similitude_Struct
00118 {
00119
00120 DBL c_x, c_y;
00121 DBL r, r2, A, A2;
00122 F_PT Ct, St, Ct2, St2;
00123 F_PT Cx, Cy;
00124 F_PT R, R2;
00125 };
00126
00127
00128 struct Fractal_Struct
00129 {
00130
00131 int Nb_Simi;
00132 SIMI Components[5 * MAX_SIMI];
00133 int Depth, Col;
00134 int Count, Speed;
00135 int Width, Height, Lx, Ly;
00136 DBL r_mean, dr_mean, dr2_mean;
00137 int Cur_Pt, Max_Pt;
00138
00139 IFSPoint *Buffer1, *Buffer2;
00140
00141
00142 };
00143
00144 static FRACTAL *Root = (FRACTAL *) NULL, *Cur_F;
00145
00146
00147 IFSPoint *Buf;
00148 static int Cur_Pt;
00149
00150
00151
00152
00153 static DBL
00154 Gauss_Rand (DBL c, DBL A, DBL S)
00155 {
00156 DBL y;
00157
00158 y = (DBL) LRAND () / MAXRAND;
00159 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
00160 if (NRAND (2))
00161 return (c + y);
00162 return (c - y);
00163 }
00164
00165 static DBL
00166 Half_Gauss_Rand (DBL c, DBL A, DBL S)
00167 {
00168 DBL y;
00169
00170 y = (DBL) LRAND () / MAXRAND;
00171 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
00172 return (c + y);
00173 }
00174
00175 static void
00176 Random_Simis (FRACTAL * F, SIMI * Cur, int i)
00177 {
00178 while (i--) {
00179 Cur->c_x = Gauss_Rand (0.0, .8, 4.0);
00180 Cur->c_y = Gauss_Rand (0.0, .8, 4.0);
00181 Cur->r = Gauss_Rand (F->r_mean, F->dr_mean, 3.0);
00182 Cur->r2 = Half_Gauss_Rand (0.0, F->dr2_mean, 2.0);
00183 Cur->A = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
00184 Cur->A2 = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
00185 Cur++;
00186 }
00187 }
00188
00189 static void
00190 free_ifs_buffers (FRACTAL * Fractal)
00191 {
00192 if (Fractal->Buffer1 != NULL) {
00193 (void) free ((void *) Fractal->Buffer1);
00194 Fractal->Buffer1 = (IFSPoint *) NULL;
00195 }
00196 if (Fractal->Buffer2 != NULL) {
00197 (void) free ((void *) Fractal->Buffer2);
00198 Fractal->Buffer2 = (IFSPoint *) NULL;
00199 }
00200 }
00201
00202
00203 static void
00204 free_ifs (FRACTAL * Fractal)
00205 {
00206 free_ifs_buffers (Fractal);
00207 }
00208
00209
00210
00211 void
00212 init_ifs (int width, int height)
00213 {
00214 int i;
00215 FRACTAL *Fractal;
00216
00217
00218
00219 if (Root == NULL) {
00220 Root = (FRACTAL *) malloc (sizeof (FRACTAL));
00221 if (Root == NULL)
00222 return;
00223 Root->Buffer1 = (IFSPoint *) NULL;
00224 Root->Buffer2 = (IFSPoint *) NULL;
00225 }
00226 Fractal = Root;
00227
00228
00229 free_ifs_buffers (Fractal);
00230
00231
00232 i = (NRAND (4)) + 2;
00233 switch (i) {
00234 case 3:
00235 Fractal->Depth = MAX_DEPTH_3;
00236 Fractal->r_mean = .6;
00237 Fractal->dr_mean = .4;
00238 Fractal->dr2_mean = .3;
00239 break;
00240
00241 case 4:
00242 Fractal->Depth = MAX_DEPTH_4;
00243 Fractal->r_mean = .5;
00244 Fractal->dr_mean = .4;
00245 Fractal->dr2_mean = .3;
00246 break;
00247
00248 case 5:
00249 Fractal->Depth = MAX_DEPTH_5;
00250 Fractal->r_mean = .5;
00251 Fractal->dr_mean = .4;
00252 Fractal->dr2_mean = .3;
00253 break;
00254
00255 default:
00256 case 2:
00257 Fractal->Depth = MAX_DEPTH_2;
00258 Fractal->r_mean = .7;
00259 Fractal->dr_mean = .3;
00260 Fractal->dr2_mean = .4;
00261 break;
00262 }
00263
00264 Fractal->Nb_Simi = i;
00265 Fractal->Max_Pt = Fractal->Nb_Simi - 1;
00266 for (i = 0; i <= Fractal->Depth + 2; ++i)
00267 Fractal->Max_Pt *= Fractal->Nb_Simi;
00268
00269 if ((Fractal->Buffer1 = (IFSPoint *) calloc (Fractal->Max_Pt,
00270 sizeof (IFSPoint))) == NULL) {
00271 free_ifs (Fractal);
00272 return;
00273 }
00274 if ((Fractal->Buffer2 = (IFSPoint *) calloc (Fractal->Max_Pt,
00275 sizeof (IFSPoint))) == NULL) {
00276 free_ifs (Fractal);
00277 return;
00278 }
00279
00280
00281 Fractal->Speed = 6;
00282 Fractal->Width = width;
00283 Fractal->Height = height;
00284 Fractal->Cur_Pt = 0;
00285 Fractal->Count = 0;
00286 Fractal->Lx = (Fractal->Width - 1) / 2;
00287 Fractal->Ly = (Fractal->Height - 1) / 2;
00288 Fractal->Col = rand () % (width * height);
00289
00290 Random_Simis (Fractal, Fractal->Components, 5 * MAX_SIMI);
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 }
00329
00330
00331
00332
00333
00334 #if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
00335 #undef inline
00336 #define inline
00337 #endif
00338 static inline void
00339 Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
00340 {
00341 F_PT xx, yy;
00342
00343 xo = xo - Simi->Cx;
00344 xo = (xo * Simi->R) >> FIX;
00345 yo = yo - Simi->Cy;
00346 yo = (yo * Simi->R) >> FIX;
00347
00348 xx = xo - Simi->Cx;
00349 xx = (xx * Simi->R2) >> FIX;
00350 yy = -yo - Simi->Cy;
00351 yy = (yy * Simi->R2) >> FIX;
00352
00353 *x =
00354 ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2)
00355 >> FIX ) + Simi->Cx;
00356 *y =
00357 ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2)
00358 >> FIX ) + Simi->Cy;
00359 }
00360
00361
00362
00363 static void
00364 Trace (FRACTAL * F, F_PT xo, F_PT yo)
00365 {
00366 F_PT x, y, i;
00367 SIMI *Cur;
00368
00369 Cur = Cur_F->Components;
00370 for (i = Cur_F->Nb_Simi; i; --i, Cur++) {
00371 Transform (Cur, xo, yo, &x, &y);
00372
00373 Buf->x = F->Lx + ((x * F->Lx) >> (FIX+1) );
00374 Buf->y = F->Ly - ((y * F->Ly) >> (FIX+1) );
00375 Buf++;
00376
00377 Cur_Pt++;
00378
00379 if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
00380 F->Depth--;
00381 Trace (F, x, y);
00382 F->Depth++;
00383 }
00384 }
00385 }
00386
00387 static void
00388 Draw_Fractal ( )
00389 {
00390 FRACTAL *F = Root;
00391 int i, j;
00392 F_PT x, y, xo, yo;
00393 SIMI *Cur, *Simi;
00394
00395 for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
00396 Cur->Cx = DBL_To_F_PT (Cur->c_x);
00397 Cur->Cy = DBL_To_F_PT (Cur->c_y);
00398
00399 Cur->Ct = DBL_To_F_PT (cos (Cur->A));
00400 Cur->St = DBL_To_F_PT (sin (Cur->A));
00401 Cur->Ct2 = DBL_To_F_PT (cos (Cur->A2));
00402 Cur->St2 = DBL_To_F_PT (sin (Cur->A2));
00403
00404 Cur->R = DBL_To_F_PT (Cur->r);
00405 Cur->R2 = DBL_To_F_PT (Cur->r2);
00406 }
00407
00408
00409 Cur_Pt = 0;
00410 Cur_F = F;
00411 Buf = F->Buffer2;
00412 for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
00413 xo = Cur->Cx;
00414 yo = Cur->Cy;
00415 for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
00416 if (Simi == Cur)
00417 continue;
00418 Transform (Simi, xo, yo, &x, &y);
00419 Trace (F, x, y);
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 F->Cur_Pt = Cur_Pt;
00454 Buf = F->Buffer1;
00455 F->Buffer1 = F->Buffer2;
00456 F->Buffer2 = Buf;
00457 }
00458
00459
00460 IFSPoint *
00461 draw_ifs ( int *nbpt)
00462 {
00463 int i;
00464 DBL u, uu, v, vv, u0, u1, u2, u3;
00465 SIMI *S, *S1, *S2, *S3, *S4;
00466 FRACTAL *F;
00467
00468 if (Root == NULL)
00469 return NULL;
00470 F = Root;
00471 if (F->Buffer1 == NULL)
00472 return NULL;
00473
00474 u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
00475 uu = u * u;
00476 v = 1.0 - u;
00477 vv = v * v;
00478 u0 = vv * v;
00479 u1 = 3.0 * vv * u;
00480 u2 = 3.0 * v * uu;
00481 u3 = u * uu;
00482
00483 S = F->Components;
00484 S1 = S + F->Nb_Simi;
00485 S2 = S1 + F->Nb_Simi;
00486 S3 = S2 + F->Nb_Simi;
00487 S4 = S3 + F->Nb_Simi;
00488
00489 for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
00490 S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
00491 S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
00492 S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
00493 S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
00494 S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
00495 S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
00496 }
00497
00498
00499
00500 Draw_Fractal ( );
00501
00502 if (F->Count >= 1000 / F->Speed) {
00503 S = F->Components;
00504 S1 = S + F->Nb_Simi;
00505 S2 = S1 + F->Nb_Simi;
00506 S3 = S2 + F->Nb_Simi;
00507 S4 = S3 + F->Nb_Simi;
00508
00509 for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
00510 S2->c_x = 2.0 * S4->c_x - S3->c_x;
00511 S2->c_y = 2.0 * S4->c_y - S3->c_y;
00512 S2->r = 2.0 * S4->r - S3->r;
00513 S2->r2 = 2.0 * S4->r2 - S3->r2;
00514 S2->A = 2.0 * S4->A - S3->A;
00515 S2->A2 = 2.0 * S4->A2 - S3->A2;
00516
00517 *S1 = *S4;
00518 }
00519 Random_Simis (F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
00520
00521 Random_Simis (F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
00522
00523 F->Count = 0;
00524 }
00525 else
00526 F->Count++;
00527
00528 F->Col++;
00529
00530
00531 (*nbpt) = Cur_Pt;
00532 return F->Buffer2;
00533
00534 }
00535
00536
00537
00538
00539 void
00540 release_ifs ()
00541 {
00542 if (Root != NULL) {
00543 free_ifs(Root);
00544 (void) free ((void *) Root);
00545 Root = (FRACTAL *) NULL;
00546 }
00547 }
00548
00549