Commits

Frederic De Groef  committed 835e8de

added a cython implementation

  • Participants
  • Parent commits 4b3fe67

Comments (0)

Files changed (5)

File src/demo_cython.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+import numpy as np
+import matplotlib.pyplot as plt
+import noise_cy as noise
+import math as m
+import time
+
+
+
+_p = [51, 3, 190, 211, 218, 30, 27, 64, 65, 158, 42, 99, 78, 48,
+ 238, 245, 228, 243, 38, 98, 2, 115, 226, 210, 36, 87, 9, 101, 23, 63,
+ 40, 154, 34, 181, 20, 168, 104, 167, 144, 165, 28, 68, 19, 247, 14,
+ 171, 44, 80, 102, 222, 159, 135, 49, 84, 17, 95, 209, 117, 136, 235,
+ 237, 197, 206, 143, 217, 59, 246, 239, 5, 160, 43, 103, 176, 35, 45,
+ 72, 113, 26, 193, 172, 227, 57, 131, 153, 70, 123, 139, 156, 255, 75,
+ 12, 204, 97, 61, 1, 105, 91, 121, 108, 180, 134, 189, 169, 50, 185,
+ 71, 194, 253, 79, 252, 41, 215, 219, 93, 145, 127, 232, 90, 7, 73,
+ 83, 230, 201, 170, 60, 138, 100, 150, 220, 21, 147, 141, 16, 25, 110,
+ 195, 216, 24, 109, 250, 89, 88, 236, 233, 116, 202, 112, 130, 85, 52,
+ 107, 6, 163, 129, 125, 119, 157, 221, 186, 140, 114, 122, 207, 229,
+ 22, 18, 198, 39, 56, 86, 111, 46, 62, 8, 191, 224, 69, 249, 15, 67,
+ 132, 234, 173, 182, 124, 240, 251, 58, 244, 241, 96, 148, 199, 74,
+ 212, 94, 133, 126, 178, 254, 242, 231, 174, 76, 0, 55, 183, 29, 146,
+ 77, 208, 188, 213, 164, 161, 53, 200, 33, 203, 162, 11, 166, 179,
+ 187, 196, 248, 151, 92, 177, 32, 81, 82, 31, 155, 120, 10, 4, 223,
+ 184, 175, 37, 205, 225, 66, 128, 214, 13, 142, 118, 54, 137, 152,
+ 192, 47, 106, 149]
+
+#p = range(256)
+#random.shuffle(p)
+
+p = np.array(_p)
+TAU = 2 * m.pi
+N = 8
+gradients2D = [(m.cos(i * TAU / N), m.sin(i * TAU / N)) for i in range(N)]
+
+
+if __name__ == '__main__':
+    w, h = 1024,1024
+    n = 8
+
+    time_before = time.time()
+    texture =  noise.make_turbulence_texture(w,h, n, p, gradients2D)
+    print "Time elapsed : %f seconds [size=(%d, %d), fractal=%d]" % (time.time() - time_before, w, h, n)
+    
+
+    #normalize & show
+    texture/=texture.max()
+    plt.imshow(texture)#, cmap=plt.cm.gray)
+    plt.colorbar()
+    plt.show()

File src/demo_matplotlib.py

 import numpy as np
 import matplotlib.pyplot as plt
 import noise
+import time
 
 
 if __name__ == '__main__':
-    w, h = 256,256
+    w, h = 512,512
     n = 8
-    fractal_sum = np.zeros((w, h))
-    turbulence = np.zeros_like(fractal_sum)
-    ridges = np.zeros_like(fractal_sum)
-    noise_values = np.zeros_like(fractal_sum)
 
+    noise_values = np.zeros((w, h))
+
+    time_before = time.time()
     for i in range(w-1):
         for j in range(h-1):
-            x, y = float(i)/(w), float(j)/(h)
-            #fractal_sum[i, j] = noise.make_fractal_sum_2D(x, y, n)
-            #turbulence[i, j] = noise.make_turbulence_2D(x, y, n)
-            #noise_values[i, j] = noise.make_ridgedmf(x, y, n, 5.0)
-            noise_values[i, j] = noise.make_marble_2D(x, y, n)
-        
+            x, y = float(i)/(w-1), float(j)/(h-1)
+            noise_values[i, j] = noise.make_fractal_sum_2D(x, y, n)
+
+    print "Time elapsed : %f seconds [size=(%d, %d), fractal=%d]" % (time.time() - time_before, w, h, n)
     values = noise_values
     #normalize & show 
     values/=values.max()
-    plt.imshow(values, cmap=plt.cm.gray)
+    plt.imshow(values)#, cmap=plt.cm.gray)
     plt.colorbar()
     plt.show()
 
+n

File src/noise.py

 import math as m
 
 
-#p = range(256)
-#random.shuffle(p)
 
 p = [51, 3, 190, 211, 218, 30, 27, 64, 65, 158, 42, 99, 78, 48,
  238, 245, 228, 243, 38, 98, 2, 115, 226, 210, 36, 87, 9, 101, 23, 63,
  184, 175, 37, 205, 225, 66, 128, 214, 13, 142, 118, 54, 137, 152,
  192, 47, 106, 149]
 
-        
+p = range(256)
+random.shuffle(p)
 
-gradients2D = []
-for i in [0, m.pi/2, m.pi, 3*m.pi/2, m.pi/4, 3*m.pi/4, 5*m.pi/4, 7*m.pi/4]:
-    gradients2D.append((m.cos(i), m.sin(i)))
+TAU = 2 * m.pi
+N = 8
+gradients2D = [(m.cos(i * TAU / N), m.sin(i * TAU / N)) for i in range(N)]
+
+#gradients2D = []
+#for i in [0, m.pi/2, m.pi, 3*m.pi/2, m.pi/4, 3*m.pi/4, 5*m.pi/4, 7*m.pi/4]:
+#    gradients2D.append((m.cos(i), m.sin(i)))
 
 
 def get_gradient2D(i, j):

File src/noise_cy.pyx

+from __future__ import division
+import numpy as np
+cimport numpy as np
+import cython
+
+cdef extern from "math.h":
+    cdef double floor(double)
+    cdef double cos(double)
+    cdef double sin(double)
+    cdef double abs(double)
+
+
+
+def get_gradient2D(int i, int j, np.ndarray[int] p, gradients2D):
+    cdef int I, J
+    I = i & 0xff
+    J =	j & 0xff
+    cdef int idx1 = (I + p[J])&0xff
+    cdef int idx = p[idx1] % 8
+    return gradients2D[idx]
+
+cpdef double lerp(double a, double b, double alpha):
+    return a*(1-alpha) + b*(alpha)
+
+cpdef double dot(v1, v2):
+    return v1[0]*v2[0] + v1[1]*v2[1]
+
+
+cpdef double f(double t):
+    return (t * ( t * ( t * (6.0*t**2 - 15.0*t + 10.0))))
+
+
+
+
+def noise2D(double x, double y, np.ndarray[int] p, gradients2D):
+    cdef int i, j 
+    i = int(floor(x))
+    j =	int(floor(y))
+    g00 = get_gradient2D(i,   j, p, gradients2D)
+    g01 = get_gradient2D(i,   j+1, p, gradients2D)
+    g10 = get_gradient2D(i+1, j, p, gradients2D)
+    g11 = get_gradient2D(i+1, j+1, p, gradients2D)
+ 
+    cdef double u, v 
+    u = (x-i)
+    v =	(y-j)
+ 
+    # intepolation ramps
+    cdef double n00 = dot(g00, (u, v))
+    cdef double n01 = dot(g01, (u, v-1))
+    cdef double n10 = dot(g10, (u-1, v))
+    cdef double n11 = dot(g11, (u-1, v-1))
+ 
+    # blending
+    cdef double nx0 = lerp(n00, n10, f(u))
+    cdef double nx1 = lerp(n01, n11, f(u))
+ 
+    cdef double nxy = lerp(nx0, nx1, f(v))
+ 
+    return nxy
+
+
+def make_turbulence2D(double x, double y, int n_octaves, double lacunarity, double gain, np.ndarray[int] p, gradients2D):
+    cdef double sum = 0.0
+    cdef double freq = 1.0
+    cdef ampl = 0.5
+    cdef int i
+    for i in range(n_octaves):
+        sum += noise2D(x*freq, y*freq, p, gradients2D) * ampl
+        freq *= lacunarity  # 2.0**i
+        ampl *= gain         # 0.5**
+    return sum
+
+
+
+
+
+def make_turbulence_texture(int w, int h, int n_octaves,  np.ndarray[int] p, gradients2D):
+    cdef np.ndarray[double, ndim=2] out = np.zeros((w,h))
+    cdef int i, j
+    cdef double x, y
+    for i in range(w-1):
+        for j in range(h-1):
+            x, y = i/(w - 1), j/(h - 1)
+            #print x, y
+            val = make_turbulence2D(x, y, n_octaves, 2.0, 0.5, p, gradients2D)
+            #print val
+            out[i, j] = val
+    return out

File src/setup.py

+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+import numpy as np
+
+ext_modules = [Extension("noise_cy", ["noise_cy.pyx"],  include_dirs = [np.get_include()])]
+
+setup(
+  name = 'perlin_noise',
+  cmdclass = {'build_ext': build_ext},
+  ext_modules = ext_modules
+)