Welcome, guest | Sign In | My Account | Store | Cart

This method uses inverse IFS transformations (assume new x, new y are known and x, y are unknown and solve the equation), and unlike IFS algorithm, it does not use a random number generator and neither the probability coefficients for each IFS transformation. (Except when IFS algorithm is used in the beginning to find bounding rectangle of the fractal.)

Python, 96 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# IFS fractals using iteration method
# FB - 20120107
import random
from collections import deque
from PIL import Image
# image size
imgx = 512
imgy = 512 # will be auto-re-adjusted according to aspect ratio of the fractal

# Fractint IFS Fern
mat=[[0.0,0.0,0.0,0.16,0.0,0.0,0.01],
     [0.85,0.04,-0.04,0.85,0.0,1.6,0.85],
     [0.2,-0.26,0.23,0.22,0.0,1.6,0.07],
     [-0.15,0.28,0.26,0.24,0.0,0.44,0.07]]

### Fractint IFS Dragon
##mat = [[0.824074, 0.281482, -0.212346,  0.864198, -1.882290, -0.110607, 0.787473],
##       [0.088272, 0.520988, -0.463889, -0.377778,  0.785360,  8.095795, 0.212527]]

### C fractal
##mat = [[0.5, -0.5, 0.5, 0.5, 0.0, 0.0, 0.5],
##       [0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5]]

### Dragon
##mat = [[0.5, -0.5, 0.5, 0.5, 0.0, 0.0, 0.5],
##       [-0.5, -0.5, 0.5, -0.5, 1.0, 0.0, 0.5]]

m = len(mat) # number of IFS transformations
# find xmin, xmax, ymin, ymax of the fractal using IFS algorithm
x = mat[0][4]
y = mat[0][5] 
xa = x
xb = x
ya = y
yb = y
for k in range(imgx * imgy):
    p = random.random()
    psum = 0.0
    for i in range(m):
        psum += mat[i][6]
        if p <= psum:
            break
    x0 = x * mat[i][0] + y * mat[i][1] + mat[i][4] 
    y  = x * mat[i][2] + y * mat[i][3] + mat[i][5] 
    x = x0 
    if x < xa:
        xa = x
    if x > xb:
        xb = x
    if y < ya:
        ya = y
    if y > yb:
        yb = y

imgy = int(imgy * (yb - ya) / (xb - xa)) # auto-re-adjust the aspect ratio 
image = Image.new("RGB", (imgx, imgy))

# drawing using IFS algorithm
##x=0.0
##y=0.0 
##for k in range(imgx * imgy):
##    p=random.random()
##    psum = 0.0
##    for i in range(m):
##        psum += mat[i][6]
##        if p <= psum:
##            break
##    x0 = x * mat[i][0] + y * mat[i][1] + mat[i][4] 
##    y  = x * mat[i][2] + y * mat[i][3] + mat[i][5] 
##    x = x0 
##    jx = int((x - xa) / (xb - xa) * (imgx - 1)) 
##    jy = (imgy - 1) - int((y - ya) / (yb - ya) * (imgy - 1))
##    image.putpixel((jx, jy), (255, 255, 255)) 

# drawing using iteration method
maxIt = 16 # max number of iterations allowed
for ky in range(imgy):
    for kx in range(imgx):
        x = float(kx) / (imgx - 1) * (xb - xa) + xa
        y = float(ky) / (imgy - 1) * (yb - ya) + ya
        queue = deque([])
        queue.append((x, y, 0))
        while len(queue) > 0: # iterate points until none left
            (x, y, i) = queue.popleft()
            # apply all (inverse) IFS transformations
            for j in range(m):
                d = mat[j][0] * mat[j][3] - mat[j][2] * mat[j][1]
                if d != 0.0:
                    xnew = ((x - mat[j][4]) * mat[j][3] - (y - mat[j][5]) * mat[j][1]) / d
                    ynew = ((y - mat[j][5]) * mat[j][0] - (x - mat[j][4]) * mat[j][2]) / d
                    if xnew >= xa and xnew <= xb and ynew >= ya and ynew <= yb:
                        if i + 1 == maxIt: break
                        queue.append((xnew, ynew, i + 1))

        image.putpixel((kx, ky), (i % 8 * 32, i % 16 * 16, i % 32 * 8))
image.save("IFSfractalUsingIterationMethod.png", "PNG")