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
48
49/*****************************************************/
50
51using DBL = double;
52using F_PT = float;
53
54/*****************************************************/
55
56static constexpr uint8_t FIX { 12 };
57static constexpr uint16_t UNIT { 1<<FIX };
58static constexpr size_t MAX_SIMI { 6 };
59
60static constexpr int8_t MAX_DEPTH_2 { 10 };
61static constexpr int8_t MAX_DEPTH_3 { 6 };
62static constexpr int8_t MAX_DEPTH_4 { 4 };
63static constexpr int8_t MAX_DEPTH_5 { 2 };
64
65static inline F_PT DBL_To_F_PT(DBL x)
66{ return static_cast<F_PT>( static_cast<DBL>(UNIT) * x ); };
67
68using SIMI = struct Similitude_Struct;
69using FRACTAL = struct Fractal_Struct;
70
72{
73
79};
80
81using SimiData = std::array<SIMI,5 * MAX_SIMI>;
82
84{
85
86 size_t m_nbSimi;
93
95// Pixmap dbuf;
96// GC dbuf_gc;
97};
98
99static FRACTAL *Root = (FRACTAL *) nullptr, *Cur_F;
100
101/* Used by the Trace recursive method */
103static int Cur_Pt;
104
105/*****************************************************/
106static constexpr double MAXRAND { 2147483648.0 }; /* unsigned 1<<31 as a * * * * float */
107
108static DBL
110{
111 DBL y = static_cast<double>(MythRandom(0, (1U << 31) - 1)) / MAXRAND;
112 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
113 if (rand_bool())
114 return (c + y);
115 return (c - y);
116}
117
118static DBL
120{
121 DBL y = static_cast<double>(MythRandom(0, (1U << 31) - 1)) / MAXRAND;
122 y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
123 return (c + y);
124}
125
126static void
127Random_Simis (FRACTAL * F, SimiData &simi_set, int offset, int count)
128{
129 SIMI * Cur = &simi_set[offset];
130 while (count--) {
131 Cur->m_dCx = Gauss_Rand (0.0, .8, 4.0);
132 Cur->m_dCy = Gauss_Rand (0.0, .8, 4.0);
133 Cur->m_dR = Gauss_Rand (F->m_rMean, F->m_drMean, 3.0);
134 Cur->m_dR2 = Half_Gauss_Rand (0.0, F->m_dr2Mean, 2.0);
135 Cur->m_dA = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
136 Cur->m_dA2 = Gauss_Rand (0.0, 360.0, 4.0) * (M_PI / 180.0);
137 Cur++;
138 }
139}
140
141static void
143{
144 if (Fractal->m_buffer1 != nullptr) {
145 free ((void *) Fractal->m_buffer1);
146 Fractal->m_buffer1 = (IFSPoint *) nullptr;
147 }
148 if (Fractal->m_buffer2 != nullptr) {
149 free ((void *) Fractal->m_buffer2);
150 Fractal->m_buffer2 = (IFSPoint *) nullptr;
151 }
152}
153
154
155static void
156free_ifs (FRACTAL * Fractal)
157{
158 free_ifs_buffers (Fractal);
159}
160
161/***************************************************************/
162
163void
164init_ifs (int width, int height)
165{
166// printf ("initing ifs\n");
167
168 if (Root == nullptr) {
169 Root = (FRACTAL *) malloc (sizeof (FRACTAL));
170 if (Root == nullptr)
171 return;
172 Root->m_buffer1 = (IFSPoint *) nullptr;
173 Root->m_buffer2 = (IFSPoint *) nullptr;
174 }
175 FRACTAL *Fractal = Root;
176
177// fprintf (stderr,"--ifs freeing ex-buffers\n");
178 free_ifs_buffers (Fractal);
179// fprintf (stderr,"--ifs ok\n");
180
181 int i = MythRandomInt(2, 5); /* Number of centers */
182 switch (i) {
183 case 3:
184 Fractal->m_depth = MAX_DEPTH_3;
185 Fractal->m_rMean = .6;
186 Fractal->m_drMean = .4;
187 Fractal->m_dr2Mean = .3;
188 break;
189
190 case 4:
191 Fractal->m_depth = MAX_DEPTH_4;
192 Fractal->m_rMean = .5;
193 Fractal->m_drMean = .4;
194 Fractal->m_dr2Mean = .3;
195 break;
196
197 case 5:
198 Fractal->m_depth = MAX_DEPTH_5;
199 Fractal->m_rMean = .5;
200 Fractal->m_drMean = .4;
201 Fractal->m_dr2Mean = .3;
202 break;
203
204 default:
205 case 2:
206 Fractal->m_depth = MAX_DEPTH_2;
207 Fractal->m_rMean = .7;
208 Fractal->m_drMean = .3;
209 Fractal->m_dr2Mean = .4;
210 break;
211 }
212// fprintf( stderr, "N=%d\n", i );
213 Fractal->m_nbSimi = i;
214 Fractal->m_maxPt = Fractal->m_nbSimi - 1;
215 for (i = 0; i <= Fractal->m_depth + 2; ++i)
216 Fractal->m_maxPt *= Fractal->m_nbSimi;
217
218 Fractal->m_buffer1 = (IFSPoint *) calloc (Fractal->m_maxPt, sizeof (IFSPoint));
219 if (Fractal->m_buffer1 == nullptr) {
220 free_ifs (Fractal);
221 return;
222 }
223 Fractal->m_buffer2 = (IFSPoint *) calloc (Fractal->m_maxPt, sizeof (IFSPoint));
224 if (Fractal->m_buffer2 == nullptr) {
225 free_ifs (Fractal);
226 return;
227 }
228
229// printf ("--ifs setting params\n");
230 Fractal->m_speed = 6;
231 Fractal->m_width = width; /* modif by JeKo */
232 Fractal->m_height = height; /* modif by JeKo */
233 Fractal->m_curPt = 0;
234 Fractal->m_count = 0;
235 Fractal->m_lx = (Fractal->m_width - 1) / 2;
236 Fractal->m_ly = (Fractal->m_height - 1) / 2;
237 Fractal->m_col = MythRandomInt(0, width * height - 1); /* modif by JeKo */
238
239 Random_Simis (Fractal, Fractal->m_components, 0, 5 * MAX_SIMI);
240
241 /*
242 * #ifndef NO_DBUF
243 * if (Fractal->dbuf != None)
244 * XFreePixmap(display, Fractal->dbuf);
245 * Fractal->dbuf = XCreatePixmap(display, window,
246 * Fractal->m_width, Fractal->m_height, 1);
247 * * Allocation checked *
248 * if (Fractal->dbuf != None) {
249 * XGCValues gcv;
250 *
251 * gcv.foreground = 0;
252 * gcv.background = 0;
253 * gcv.graphics_exposures = False;
254 * gcv.function = GXcopy;
255 *
256 * if (Fractal->dbuf_gc != None)
257 * XFreeGC(display, Fractal->dbuf_gc);
258 * if ((Fractal->dbuf_gc = XCreateGC(display, Fractal->dbuf,
259 * GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
260 * &gcv)) == None) {
261 * XFreePixmap(display, Fractal->dbuf);
262 * Fractal->dbuf = None;
263 * } else {
264 * XFillRectangle(display, Fractal->dbuf,
265 * Fractal->dbuf_gc, 0, 0, Fractal->m_width, Fractal->m_height);
266 * XSetBackground(display, gc, MI_BLACK_PIXEL(mi));
267 * XSetFunction(display, gc, GXcopy);
268 * }
269 * }
270 * #endif
271 */
272 // MI_CLEARWINDOW(mi);
273
274 /* don't want any exposure events from XCopyPlane */
275 // XSetGraphicsExposures(display, gc, False);
276
277}
278
279
280/***************************************************************/
281
282/* Should be taken care of already... but just in case */
283#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
284#undef inline
285#define inline /* */
286#endif
287static inline void
288Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
289{
290 xo = xo - Simi->m_fCx;
291 xo = (xo * Simi->m_fR) / UNIT;
292 yo = yo - Simi->m_fCy;
293 yo = (yo * Simi->m_fR) / UNIT;
294
295 F_PT xx = xo - Simi->m_fCx;
296 xx = (xx * Simi->m_fR2) / UNIT;
297 F_PT yy = -yo - Simi->m_fCy;
298 yy = (yy * Simi->m_fR2) / UNIT;
299
300 *x =
301 ((xo * Simi->m_fCt - yo * Simi->m_fSt + xx * Simi->m_fCt2 - yy * Simi->m_fSt2) / UNIT ) + Simi->m_fCx;
302 *y =
303 ((xo * Simi->m_fSt + yo * Simi->m_fCt + xx * Simi->m_fSt2 + yy * Simi->m_fCt2) / UNIT ) + Simi->m_fCy;
304}
305
306/***************************************************************/
307
308static void
309Trace (FRACTAL * F, F_PT xo, F_PT yo)
310{
311 F_PT x = NAN;
312 F_PT y = NAN;
313
314 SIMI *Cur = (Cur_F->m_components).data();
315 for (int i = Cur_F->m_nbSimi; i != 0; --i, Cur++) {
316 Transform (Cur, xo, yo, &x, &y);
317
318 Buf->x = F->m_lx + ((x * F->m_lx) / (UNIT*2) );
319 Buf->y = F->m_ly - ((y * F->m_ly) / (UNIT*2) );
320 Buf++;
321
322 Cur_Pt++;
323
324 if (F->m_depth && (((x - xo) / 16) != 0.0F) && (((y - yo) / 16) != 0.0F)) {
325 F->m_depth--;
326 Trace (F, x, y);
327 F->m_depth++;
328 }
329 }
330}
331
332static void
333Draw_Fractal ( void /* ModeInfo * mi */ )
334{
335 FRACTAL *F = Root;
336 int i = 0;
337 SIMI *Cur = nullptr;
338 SIMI *Simi = nullptr;
339
340 for (Cur = (F->m_components).data(), i = F->m_nbSimi; i; --i, Cur++) {
341 Cur->m_fCx = DBL_To_F_PT (Cur->m_dCx);
342 Cur->m_fCy = DBL_To_F_PT (Cur->m_dCy);
343
344 Cur->m_fCt = DBL_To_F_PT (cos (Cur->m_dA));
345 Cur->m_fSt = DBL_To_F_PT (sin (Cur->m_dA));
346 Cur->m_fCt2 = DBL_To_F_PT (cos (Cur->m_dA2));
347 Cur->m_fSt2 = DBL_To_F_PT (sin (Cur->m_dA2));
348
349 Cur->m_fR = DBL_To_F_PT (Cur->m_dR);
350 Cur->m_fR2 = DBL_To_F_PT (Cur->m_dR2);
351 }
352
353
354 Cur_Pt = 0;
355 Cur_F = F;
356 Buf = F->m_buffer2;
357 for (Cur = (F->m_components).data(), i = F->m_nbSimi; i; --i, Cur++) {
358 F_PT xo = Cur->m_fCx;
359 F_PT yo = Cur->m_fCy;
360 int j = 0;
361 for (Simi = (F->m_components).data(), j = F->m_nbSimi; j; --j, Simi++) {
362 F_PT x = NAN;
363 F_PT y = NAN;
364 if (Simi == Cur)
365 continue;
366 Transform (Simi, xo, yo, &x, &y);
367 Trace (F, x, y);
368 }
369 }
370
371 /* Erase previous */
372
373/* if (F->m_curPt) {
374 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
375 if (F->dbuf != None) {
376 XSetForeground(display, F->dbuf_gc, 0);
377*/
378 /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->m_buffer1, F->m_curPt, * * * *
379 * CoordModeOrigin); */
380/* XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0,
381 F->m_width, F->m_height);
382 } else
383 XDrawPoints(display, window, gc, F->m_buffer1, F->m_curPt, CoordModeOrigin);
384 }
385 if (MI_NPIXELS(mi) < 2)
386 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
387 else
388 XSetForeground(display, gc, MI_PIXEL(mi, F->Col % MI_NPIXELS(mi)));
389 if (Cur_Pt) {
390 if (F->dbuf != None) {
391 XSetForeground(display, F->dbuf_gc, 1);
392 XDrawPoints(display, F->dbuf, F->dbuf_gc, F->m_buffer2, Cur_Pt,
393 CoordModeOrigin);
394 } else
395 XDrawPoints(display, window, gc, F->m_buffer2, Cur_Pt, CoordModeOrigin);
396 }
397 if (F->dbuf != None)
398 XCopyPlane(display, F->dbuf, window, gc, 0, 0, F->m_width, F->m_height, 0, 0, 1);
399*/
400
401 F->m_curPt = Cur_Pt;
402 Buf = F->m_buffer1;
403 F->m_buffer1 = F->m_buffer2;
404 F->m_buffer2 = Buf;
405}
406
407
408IFSPoint *
409draw_ifs ( /* ModeInfo * mi */ int *nbPoints)
410{
411 if (Root == nullptr)
412 return nullptr;
413 FRACTAL *F = Root; // [/*MI_SCREEN(mi)*/0];
414 if (F->m_buffer1 == nullptr)
415 return nullptr;
416
417 DBL u = (DBL) (F->m_count) * (DBL) (F->m_speed) / 1000.0;
418 DBL uu = u * u;
419 DBL v = 1.0 - u;
420 DBL vv = v * v;
421 DBL u0 = vv * v;
422 DBL u1 = 3.0 * vv * u;
423 DBL u2 = 3.0 * v * uu;
424 DBL u3 = u * uu;
425
426 SIMI *S = (F->m_components).data();
427 SIMI *S1 = &F->m_components[1 * F->m_nbSimi];
428 SIMI *S2 = &F->m_components[2 * F->m_nbSimi];
429 SIMI *S3 = &F->m_components[3 * F->m_nbSimi];
430 SIMI *S4 = &F->m_components[4 * F->m_nbSimi];
431
432 for (int i = F->m_nbSimi; i; --i, S++, S1++, S2++, S3++, S4++) {
433 S->m_dCx = (u0 * S1->m_dCx) + (u1 * S2->m_dCx) + (u2 * S3->m_dCx) + (u3 * S4->m_dCx);
434 S->m_dCy = (u0 * S1->m_dCy) + (u1 * S2->m_dCy) + (u2 * S3->m_dCy) + (u3 * S4->m_dCy);
435 S->m_dR = (u0 * S1->m_dR) + (u1 * S2->m_dR) + (u2 * S3->m_dR) + (u3 * S4->m_dR);
436 S->m_dR2 = (u0 * S1->m_dR2) + (u1 * S2->m_dR2) + (u2 * S3->m_dR2) + (u3 * S4->m_dR2);
437 S->m_dA = (u0 * S1->m_dA) + (u1 * S2->m_dA) + (u2 * S3->m_dA) + (u3 * S4->m_dA);
438 S->m_dA2 = (u0 * S1->m_dA2) + (u1 * S2->m_dA2) + (u2 * S3->m_dA2) + (u3 * S4->m_dA2);
439 }
440
441 // MI_IS_DRAWN(mi) = True;
442
443 Draw_Fractal ( /* mi */ );
444
445 if (F->m_count >= 1000 / F->m_speed) {
446 S = (F->m_components).data();
447 S1 = &F->m_components[1 * F->m_nbSimi];
448 S2 = &F->m_components[2 * F->m_nbSimi];
449 S3 = &F->m_components[3 * F->m_nbSimi];
450 S4 = &F->m_components[4 * F->m_nbSimi];
451
452 for (int i = F->m_nbSimi; i; --i, S++, S1++, S2++, S3++, S4++) {
453 S2->m_dCx = (2.0 * S4->m_dCx) - S3->m_dCx;
454 S2->m_dCy = (2.0 * S4->m_dCy) - S3->m_dCy;
455 S2->m_dR = (2.0 * S4->m_dR) - S3->m_dR;
456 S2->m_dR2 = (2.0 * S4->m_dR2) - S3->m_dR2;
457 S2->m_dA = (2.0 * S4->m_dA) - S3->m_dA;
458 S2->m_dA2 = (2.0 * S4->m_dA2) - S3->m_dA2;
459
460 *S1 = *S4;
461 }
462 Random_Simis (F, F->m_components, 3 * F->m_nbSimi, F->m_nbSimi);
463
464 Random_Simis (F, F->m_components, 4 * F->m_nbSimi, F->m_nbSimi);
465
466 F->m_count = 0;
467 }
468 else
469 {
470 F->m_count++;
471 }
472
473 F->m_col++;
474
475 /* #1 code added by JeKo */
476 (*nbPoints) = Cur_Pt;
477 return F->m_buffer2;
478 /* #1 end */
479}
480
481
482/***************************************************************/
483
484void
486{
487 if (Root != nullptr) {
488 free_ifs(Root);
489 free ((void *) Root);
490 Root = (FRACTAL *) nullptr;
491 }
492}
static constexpr double M_PI
Definition: goom_tools.h:9
float F_PT
Definition: ifs.cpp:52
static void free_ifs(FRACTAL *Fractal)
Definition: ifs.cpp:156
static FRACTAL * Cur_F
Definition: ifs.cpp:99
static void Draw_Fractal(void)
Definition: ifs.cpp:333
std::array< SIMI, 5 *MAX_SIMI > SimiData
Definition: ifs.cpp:81
void init_ifs(int width, int height)
Definition: ifs.cpp:164
static constexpr uint16_t UNIT
Definition: ifs.cpp:57
static int Cur_Pt
Definition: ifs.cpp:103
static constexpr uint8_t FIX
Definition: ifs.cpp:56
void release_ifs()
Definition: ifs.cpp:485
static constexpr int8_t MAX_DEPTH_4
Definition: ifs.cpp:62
static constexpr int8_t MAX_DEPTH_2
Definition: ifs.cpp:60
static constexpr double MAXRAND
Definition: ifs.cpp:106
double DBL
Definition: ifs.cpp:51
static constexpr int8_t MAX_DEPTH_3
Definition: ifs.cpp:61
static DBL Half_Gauss_Rand(DBL c, DBL A, DBL S)
Definition: ifs.cpp:119
IFSPoint * Buf
Definition: ifs.cpp:102
static F_PT DBL_To_F_PT(DBL x)
Definition: ifs.cpp:65
static DBL Gauss_Rand(DBL c, DBL A, DBL S)
Definition: ifs.cpp:109
static constexpr int8_t MAX_DEPTH_5
Definition: ifs.cpp:63
static void Transform(SIMI *Simi, F_PT xo, F_PT yo, F_PT *x, F_PT *y)
Definition: ifs.cpp:288
static void free_ifs_buffers(FRACTAL *Fractal)
Definition: ifs.cpp:142
static void Random_Simis(FRACTAL *F, SimiData &simi_set, int offset, int count)
Definition: ifs.cpp:127
static FRACTAL * Root
Definition: ifs.cpp:99
IFSPoint * draw_ifs(int *nbPoints)
Definition: ifs.cpp:409
static void Trace(FRACTAL *F, F_PT xo, F_PT yo)
Definition: ifs.cpp:309
static constexpr size_t MAX_SIMI
Definition: ifs.cpp:58
unsigned short uint16_t
Definition: iso6937tables.h:3
Convenience inline random number generator functions.
int MythRandomInt(int min, int max)
generate a uniformly distributed random signed int in the closed interval [min, max].
Definition: mythrandom.h:58
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20
bool rand_bool(uint32_t chance=2)
return a random bool with P(true) = 1/chance
Definition: mythrandom.h:86
int m_depth
Definition: ifs.cpp:88
int m_maxPt
Definition: ifs.cpp:92
int m_speed
Definition: ifs.cpp:89
DBL m_rMean
Definition: ifs.cpp:91
size_t m_nbSimi
Definition: ifs.cpp:86
IFSPoint * m_buffer2
Definition: ifs.cpp:94
int m_col
Definition: ifs.cpp:88
int m_curPt
Definition: ifs.cpp:92
int m_width
Definition: ifs.cpp:90
IFSPoint * m_buffer1
Definition: ifs.cpp:94
int m_height
Definition: ifs.cpp:90
DBL m_dr2Mean
Definition: ifs.cpp:91
SimiData m_components
Definition: ifs.cpp:87
int m_lx
Definition: ifs.cpp:90
DBL m_drMean
Definition: ifs.cpp:91
int m_count
Definition: ifs.cpp:89
int m_ly
Definition: ifs.cpp:90
Definition: ifs.h:11
int32_t x
Definition: ifs.h:12
int32_t y
Definition: ifs.h:12