MythTV master
ifs.cpp
Go to the documentation of this file.
1/* -*- Mode: C; tab-width: 4 -*- */
2/* ifs --- modified iterated functions system */
3
4//#if !defined( lint ) && !defined( SABER )
5//static const char sccsid[] = "@(#)ifs.c 5.00 2002/04/11 baffe";
6//#endif
7
8/*-
9 * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
22 *
23 * If this mode is weird and you have an old MetroX server, it is buggy.
24 * There is a free SuSE-enhanced MetroX X server that is fine.
25 *
26 * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
27 *
28 * Revision History:
29 * 11-Apr-2002: Make ifs.c system-indendant. (ifs.h added)
30 * 01-Nov-2000: Allocation checks
31 * 10-May-1997: jwz@jwz.org: turned into a standalone program.
32 * Made it render into an offscreen bitmap and then copy
33 * that onto the screen, to reduce flicker.
34 */
35
36//#ifdef STANDALONE
37
38#include <array>
39#include <cmath>
40#include <cstdio>
41#include <cstdlib>
42
43#include "ifs.h"
44#include "goom_core.h"
45#include "goom_tools.h"
46
47
48static inline long LRAND() { return static_cast<long>( RAND() & 0x7fffffff); }
49static inline int NRAND(int n) { return static_cast<int>( LRAND() % n ); }
50static constexpr double MAXRAND { 2147483648.0 }; /* unsigned 1<<31 as a * * * * float */
51
52/*****************************************************/
53
54using DBL = double;
55using F_PT = float;
56
57/*****************************************************/
58
59static constexpr uint8_t FIX { 12 };
60static constexpr uint16_t UNIT { 1<<FIX };
61static constexpr size_t MAX_SIMI { 6 };
62
63static constexpr int8_t MAX_DEPTH_2 { 10 };
64static constexpr int8_t MAX_DEPTH_3 { 6 };
65static constexpr int8_t MAX_DEPTH_4 { 4 };
66static constexpr int8_t MAX_DEPTH_5 { 2 };
67
68static inline F_PT DBL_To_F_PT(DBL x)
69{ return static_cast<F_PT>( static_cast<DBL>(UNIT) * x ); };
70
71using SIMI = struct Similitude_Struct;
72using FRACTAL = struct Fractal_Struct;
73
75{
76
82};
83
84using SimiData = std::array<SIMI,5 * MAX_SIMI>;
85
87{
88
89 size_t m_nbSimi;
96
98// Pixmap dbuf;
99// GC dbuf_gc;
100};
101
102static FRACTAL *Root = (FRACTAL *) nullptr, *Cur_F;
103
104/* Used by the Trace recursive method */
106static int Cur_Pt;
107
108/*****************************************************/
109
110static DBL
112{
113 DBL y = (DBL) LRAND () / MAXRAND;
114 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
115 if (NRAND (2))
116 return (c + y);
117 return (c - y);
118}
119
120static DBL
122{
123 DBL y = (DBL) LRAND () / MAXRAND;
124 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
125 return (c + y);
126}
127
128static void
129Random_Simis (FRACTAL * F, SimiData &simi_set, int offset, int count)
130{
131 SIMI * Cur = &simi_set[offset];
132 while (count--) {
133 Cur->m_dCx = Gauss_Rand (0.0, .8, 4.0);
134 Cur->m_dCy = Gauss_Rand (0.0, .8, 4.0);
135 Cur->m_dR = Gauss_Rand (F->m_rMean, F->m_drMean, 3.0);
136 Cur->m_dR2 = Half_Gauss_Rand (0.0, F->m_dr2Mean, 2.0);
137 Cur->m_dA = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
138 Cur->m_dA2 = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
139 Cur++;
140 }
141}
142
143static void
145{
146 if (Fractal->m_buffer1 != nullptr) {
147 free ((void *) Fractal->m_buffer1);
148 Fractal->m_buffer1 = (IFSPoint *) nullptr;
149 }
150 if (Fractal->m_buffer2 != nullptr) {
151 free ((void *) Fractal->m_buffer2);
152 Fractal->m_buffer2 = (IFSPoint *) nullptr;
153 }
154}
155
156
157static void
158free_ifs (FRACTAL * Fractal)
159{
160 free_ifs_buffers (Fractal);
161}
162
163/***************************************************************/
164
165void
166init_ifs (int width, int height)
167{
168// printf ("initing ifs\n");
169
170 if (Root == nullptr) {
171 Root = (FRACTAL *) malloc (sizeof (FRACTAL));
172 if (Root == nullptr)
173 return;
174 Root->m_buffer1 = (IFSPoint *) nullptr;
175 Root->m_buffer2 = (IFSPoint *) nullptr;
176 }
177 FRACTAL *Fractal = Root;
178
179// fprintf (stderr,"--ifs freeing ex-buffers\n");
180 free_ifs_buffers (Fractal);
181// fprintf (stderr,"--ifs ok\n");
182
183 int i = (NRAND (4)) + 2; /* Number of centers */
184 switch (i) {
185 case 3:
186 Fractal->m_depth = MAX_DEPTH_3;
187 Fractal->m_rMean = .6;
188 Fractal->m_drMean = .4;
189 Fractal->m_dr2Mean = .3;
190 break;
191
192 case 4:
193 Fractal->m_depth = MAX_DEPTH_4;
194 Fractal->m_rMean = .5;
195 Fractal->m_drMean = .4;
196 Fractal->m_dr2Mean = .3;
197 break;
198
199 case 5:
200 Fractal->m_depth = MAX_DEPTH_5;
201 Fractal->m_rMean = .5;
202 Fractal->m_drMean = .4;
203 Fractal->m_dr2Mean = .3;
204 break;
205
206 default:
207 case 2:
208 Fractal->m_depth = MAX_DEPTH_2;
209 Fractal->m_rMean = .7;
210 Fractal->m_drMean = .3;
211 Fractal->m_dr2Mean = .4;
212 break;
213 }
214// fprintf( stderr, "N=%d\n", i );
215 Fractal->m_nbSimi = i;
216 Fractal->m_maxPt = Fractal->m_nbSimi - 1;
217 for (i = 0; i <= Fractal->m_depth + 2; ++i)
218 Fractal->m_maxPt *= Fractal->m_nbSimi;
219
220 Fractal->m_buffer1 = (IFSPoint *) calloc (Fractal->m_maxPt, sizeof (IFSPoint));
221 if (Fractal->m_buffer1 == nullptr) {
222 free_ifs (Fractal);
223 return;
224 }
225 Fractal->m_buffer2 = (IFSPoint *) calloc (Fractal->m_maxPt, sizeof (IFSPoint));
226 if (Fractal->m_buffer2 == nullptr) {
227 free_ifs (Fractal);
228 return;
229 }
230
231// printf ("--ifs setting params\n");
232 Fractal->m_speed = 6;
233 Fractal->m_width = width; /* modif by JeKo */
234 Fractal->m_height = height; /* modif by JeKo */
235 Fractal->m_curPt = 0;
236 Fractal->m_count = 0;
237 Fractal->m_lx = (Fractal->m_width - 1) / 2;
238 Fractal->m_ly = (Fractal->m_height - 1) / 2;
239 Fractal->m_col = goom_rand () % (width * height); /* modif by JeKo */
240
241 Random_Simis (Fractal, Fractal->m_components, 0, 5 * MAX_SIMI);
242
243 /*
244 * #ifndef NO_DBUF
245 * if (Fractal->dbuf != None)
246 * XFreePixmap(display, Fractal->dbuf);
247 * Fractal->dbuf = XCreatePixmap(display, window,
248 * Fractal->m_width, Fractal->m_height, 1);
249 * * Allocation checked *
250 * if (Fractal->dbuf != None) {
251 * XGCValues gcv;
252 *
253 * gcv.foreground = 0;
254 * gcv.background = 0;
255 * gcv.graphics_exposures = False;
256 * gcv.function = GXcopy;
257 *
258 * if (Fractal->dbuf_gc != None)
259 * XFreeGC(display, Fractal->dbuf_gc);
260 * if ((Fractal->dbuf_gc = XCreateGC(display, Fractal->dbuf,
261 * GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
262 * &gcv)) == None) {
263 * XFreePixmap(display, Fractal->dbuf);
264 * Fractal->dbuf = None;
265 * } else {
266 * XFillRectangle(display, Fractal->dbuf,
267 * Fractal->dbuf_gc, 0, 0, Fractal->m_width, Fractal->m_height);
268 * XSetBackground(display, gc, MI_BLACK_PIXEL(mi));
269 * XSetFunction(display, gc, GXcopy);
270 * }
271 * }
272 * #endif
273 */
274 // MI_CLEARWINDOW(mi);
275
276 /* don't want any exposure events from XCopyPlane */
277 // XSetGraphicsExposures(display, gc, False);
278
279}
280
281
282/***************************************************************/
283
284/* Should be taken care of already... but just in case */
285#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
286#undef inline
287#define inline /* */
288#endif
289static inline void
290Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
291{
292 xo = xo - Simi->m_fCx;
293 xo = (xo * Simi->m_fR) / UNIT;
294 yo = yo - Simi->m_fCy;
295 yo = (yo * Simi->m_fR) / UNIT;
296
297 F_PT xx = xo - Simi->m_fCx;
298 xx = (xx * Simi->m_fR2) / UNIT;
299 F_PT yy = -yo - Simi->m_fCy;
300 yy = (yy * Simi->m_fR2) / UNIT;
301
302 *x =
303 ((xo * Simi->m_fCt - yo * Simi->m_fSt + xx * Simi->m_fCt2 - yy * Simi->m_fSt2) / UNIT ) + Simi->m_fCx;
304 *y =
305 ((xo * Simi->m_fSt + yo * Simi->m_fCt + xx * Simi->m_fSt2 + yy * Simi->m_fCt2) / UNIT ) + Simi->m_fCy;
306}
307
308/***************************************************************/
309
310static void
311Trace (FRACTAL * F, F_PT xo, F_PT yo)
312{
313 F_PT x = NAN;
314 F_PT y = NAN;
315
316 SIMI *Cur = (Cur_F->m_components).data();
317 for (int i = Cur_F->m_nbSimi; i != 0; --i, Cur++) {
318 Transform (Cur, xo, yo, &x, &y);
319
320 Buf->x = F->m_lx + ((x * F->m_lx) / (UNIT*2) );
321 Buf->y = F->m_ly - ((y * F->m_ly) / (UNIT*2) );
322 Buf++;
323
324 Cur_Pt++;
325
326 if (F->m_depth && (((x - xo) / 16) != 0.0F) && (((y - yo) / 16) != 0.0F)) {
327 F->m_depth--;
328 Trace (F, x, y);
329 F->m_depth++;
330 }
331 }
332}
333
334static void
335Draw_Fractal ( void /* ModeInfo * mi */ )
336{
337 FRACTAL *F = Root;
338 int i = 0;
339 SIMI *Cur = nullptr;
340 SIMI *Simi = nullptr;
341
342 for (Cur = (F->m_components).data(), i = F->m_nbSimi; i; --i, Cur++) {
343 Cur->m_fCx = DBL_To_F_PT (Cur->m_dCx);
344 Cur->m_fCy = DBL_To_F_PT (Cur->m_dCy);
345
346 Cur->m_fCt = DBL_To_F_PT (cos (Cur->m_dA));
347 Cur->m_fSt = DBL_To_F_PT (sin (Cur->m_dA));
348 Cur->m_fCt2 = DBL_To_F_PT (cos (Cur->m_dA2));
349 Cur->m_fSt2 = DBL_To_F_PT (sin (Cur->m_dA2));
350
351 Cur->m_fR = DBL_To_F_PT (Cur->m_dR);
352 Cur->m_fR2 = DBL_To_F_PT (Cur->m_dR2);
353 }
354
355
356 Cur_Pt = 0;
357 Cur_F = F;
358 Buf = F->m_buffer2;
359 for (Cur = (F->m_components).data(), i = F->m_nbSimi; i; --i, Cur++) {
360 F_PT xo = Cur->m_fCx;
361 F_PT yo = Cur->m_fCy;
362 int j = 0;
363 for (Simi = (F->m_components).data(), j = F->m_nbSimi; j; --j, Simi++) {
364 F_PT x = NAN;
365 F_PT y = NAN;
366 if (Simi == Cur)
367 continue;
368 Transform (Simi, xo, yo, &x, &y);
369 Trace (F, x, y);
370 }
371 }
372
373 /* Erase previous */
374
375/* if (F->m_curPt) {
376 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
377 if (F->dbuf != None) {
378 XSetForeground(display, F->dbuf_gc, 0);
379*/
380 /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->m_buffer1, F->m_curPt, * * * *
381 * CoordModeOrigin); */
382/* XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0,
383 F->m_width, F->m_height);
384 } else
385 XDrawPoints(display, window, gc, F->m_buffer1, F->m_curPt, CoordModeOrigin);
386 }
387 if (MI_NPIXELS(mi) < 2)
388 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
389 else
390 XSetForeground(display, gc, MI_PIXEL(mi, F->Col % MI_NPIXELS(mi)));
391 if (Cur_Pt) {
392 if (F->dbuf != None) {
393 XSetForeground(display, F->dbuf_gc, 1);
394 XDrawPoints(display, F->dbuf, F->dbuf_gc, F->m_buffer2, Cur_Pt,
395 CoordModeOrigin);
396 } else
397 XDrawPoints(display, window, gc, F->m_buffer2, Cur_Pt, CoordModeOrigin);
398 }
399 if (F->dbuf != None)
400 XCopyPlane(display, F->dbuf, window, gc, 0, 0, F->m_width, F->m_height, 0, 0, 1);
401*/
402
403 F->m_curPt = Cur_Pt;
404 Buf = F->m_buffer1;
405 F->m_buffer1 = F->m_buffer2;
406 F->m_buffer2 = Buf;
407}
408
409
410IFSPoint *
411draw_ifs ( /* ModeInfo * mi */ int *nbPoints)
412{
413 if (Root == nullptr)
414 return nullptr;
415 FRACTAL *F = Root; // [/*MI_SCREEN(mi)*/0];
416 if (F->m_buffer1 == nullptr)
417 return nullptr;
418
419 DBL u = (DBL) (F->m_count) * (DBL) (F->m_speed) / 1000.0;
420 DBL uu = u * u;
421 DBL v = 1.0 - u;
422 DBL vv = v * v;
423 DBL u0 = vv * v;
424 DBL u1 = 3.0 * vv * u;
425 DBL u2 = 3.0 * v * uu;
426 DBL u3 = u * uu;
427
428 SIMI *S = (F->m_components).data();
429 SIMI *S1 = &F->m_components[1 * F->m_nbSimi];
430 SIMI *S2 = &F->m_components[2 * F->m_nbSimi];
431 SIMI *S3 = &F->m_components[3 * F->m_nbSimi];
432 SIMI *S4 = &F->m_components[4 * F->m_nbSimi];
433
434 for (int i = F->m_nbSimi; i; --i, S++, S1++, S2++, S3++, S4++) {
435 S->m_dCx = (u0 * S1->m_dCx) + (u1 * S2->m_dCx) + (u2 * S3->m_dCx) + (u3 * S4->m_dCx);
436 S->m_dCy = (u0 * S1->m_dCy) + (u1 * S2->m_dCy) + (u2 * S3->m_dCy) + (u3 * S4->m_dCy);
437 S->m_dR = (u0 * S1->m_dR) + (u1 * S2->m_dR) + (u2 * S3->m_dR) + (u3 * S4->m_dR);
438 S->m_dR2 = (u0 * S1->m_dR2) + (u1 * S2->m_dR2) + (u2 * S3->m_dR2) + (u3 * S4->m_dR2);
439 S->m_dA = (u0 * S1->m_dA) + (u1 * S2->m_dA) + (u2 * S3->m_dA) + (u3 * S4->m_dA);
440 S->m_dA2 = (u0 * S1->m_dA2) + (u1 * S2->m_dA2) + (u2 * S3->m_dA2) + (u3 * S4->m_dA2);
441 }
442
443 // MI_IS_DRAWN(mi) = True;
444
445 Draw_Fractal ( /* mi */ );
446
447 if (F->m_count >= 1000 / F->m_speed) {
448 S = (F->m_components).data();
449 S1 = &F->m_components[1 * F->m_nbSimi];
450 S2 = &F->m_components[2 * F->m_nbSimi];
451 S3 = &F->m_components[3 * F->m_nbSimi];
452 S4 = &F->m_components[4 * F->m_nbSimi];
453
454 for (int i = F->m_nbSimi; i; --i, S++, S1++, S2++, S3++, S4++) {
455 S2->m_dCx = (2.0 * S4->m_dCx) - S3->m_dCx;
456 S2->m_dCy = (2.0 * S4->m_dCy) - S3->m_dCy;
457 S2->m_dR = (2.0 * S4->m_dR) - S3->m_dR;
458 S2->m_dR2 = (2.0 * S4->m_dR2) - S3->m_dR2;
459 S2->m_dA = (2.0 * S4->m_dA) - S3->m_dA;
460 S2->m_dA2 = (2.0 * S4->m_dA2) - S3->m_dA2;
461
462 *S1 = *S4;
463 }
464 Random_Simis (F, F->m_components, 3 * F->m_nbSimi, F->m_nbSimi);
465
466 Random_Simis (F, F->m_components, 4 * F->m_nbSimi, F->m_nbSimi);
467
468 F->m_count = 0;
469 }
470 else
471 {
472 F->m_count++;
473 }
474
475 F->m_col++;
476
477 /* #1 code added by JeKo */
478 (*nbPoints) = Cur_Pt;
479 return F->m_buffer2;
480 /* #1 end */
481}
482
483
484/***************************************************************/
485
486void
488{
489 if (Root != nullptr) {
490 free_ifs(Root);
491 free ((void *) Root);
492 Root = (FRACTAL *) nullptr;
493 }
494}
guint32 goom_rand(void)
Definition: goom_core.cpp:972
static constexpr double M_PI
Definition: goom_tools.h:9
static int RAND(void)
Definition: goom_tools.h:29
float F_PT
Definition: ifs.cpp:55
static void free_ifs(FRACTAL *Fractal)
Definition: ifs.cpp:158
static FRACTAL * Cur_F
Definition: ifs.cpp:102
static void Draw_Fractal(void)
Definition: ifs.cpp:335
std::array< SIMI, 5 *MAX_SIMI > SimiData
Definition: ifs.cpp:84
void init_ifs(int width, int height)
Definition: ifs.cpp:166
static constexpr uint16_t UNIT
Definition: ifs.cpp:60
static long LRAND()
Definition: ifs.cpp:48
static int Cur_Pt
Definition: ifs.cpp:106
static constexpr uint8_t FIX
Definition: ifs.cpp:59
void release_ifs()
Definition: ifs.cpp:487
static constexpr int8_t MAX_DEPTH_4
Definition: ifs.cpp:65
static constexpr int8_t MAX_DEPTH_2
Definition: ifs.cpp:63
static constexpr double MAXRAND
Definition: ifs.cpp:50
double DBL
Definition: ifs.cpp:54
static constexpr int8_t MAX_DEPTH_3
Definition: ifs.cpp:64
static DBL Half_Gauss_Rand(DBL c, DBL A, DBL S)
Definition: ifs.cpp:121
IFSPoint * Buf
Definition: ifs.cpp:105
static F_PT DBL_To_F_PT(DBL x)
Definition: ifs.cpp:68
static int NRAND(int n)
Definition: ifs.cpp:49
static DBL Gauss_Rand(DBL c, DBL A, DBL S)
Definition: ifs.cpp:111
static constexpr int8_t MAX_DEPTH_5
Definition: ifs.cpp:66
static void Transform(SIMI *Simi, F_PT xo, F_PT yo, F_PT *x, F_PT *y)
Definition: ifs.cpp:290
static void free_ifs_buffers(FRACTAL *Fractal)
Definition: ifs.cpp:144
static void Random_Simis(FRACTAL *F, SimiData &simi_set, int offset, int count)
Definition: ifs.cpp:129
static FRACTAL * Root
Definition: ifs.cpp:102
IFSPoint * draw_ifs(int *nbPoints)
Definition: ifs.cpp:411
static void Trace(FRACTAL *F, F_PT xo, F_PT yo)
Definition: ifs.cpp:311
static constexpr size_t MAX_SIMI
Definition: ifs.cpp:61
unsigned short uint16_t
Definition: iso6937tables.h:3
int m_depth
Definition: ifs.cpp:91
int m_maxPt
Definition: ifs.cpp:95
int m_speed
Definition: ifs.cpp:92
DBL m_rMean
Definition: ifs.cpp:94
size_t m_nbSimi
Definition: ifs.cpp:89
IFSPoint * m_buffer2
Definition: ifs.cpp:97
int m_col
Definition: ifs.cpp:91
int m_curPt
Definition: ifs.cpp:95
int m_width
Definition: ifs.cpp:93
IFSPoint * m_buffer1
Definition: ifs.cpp:97
int m_height
Definition: ifs.cpp:93
DBL m_dr2Mean
Definition: ifs.cpp:94
SimiData m_components
Definition: ifs.cpp:90
int m_lx
Definition: ifs.cpp:93
DBL m_drMean
Definition: ifs.cpp:94
int m_count
Definition: ifs.cpp:92
int m_ly
Definition: ifs.cpp:93
Definition: ifs.h:11
gint32 y
Definition: ifs.h:12
gint32 x
Definition: ifs.h:12