Module pyxyz.perlin

Simple 2d Perlin noise implementation, based on https://github.com/karlll/perlin2d.py

Expand source code
"""Simple 2d Perlin noise implementation, based on https://github.com/karlll/perlin2d.py"""
import math
import random

W = 255
H = 255
gradtable = [(0, 0) for i in range(0, W*H)]

def _precalc_gradtable():
    rnd = random.Random()
    for i in range(0, H):
        for j in range(0, W):
            x = float((rnd.randint(1, 2*W))-W)/W
            y = float((rnd.randint(1, 2*H))-H)/H
            s = math.sqrt(x * x + y * y)
            if s != 0:
                x = x / s
                y = y / s
            else:
                x = 0
                y = 0
            gradtable[i*H+j] = (x, y)

#calculate dot product for v1 and v2
def _dot(v1, v2):
    return (v1[0]*v2[0]) + (v1[1]*v2[1])

# get a pseudorandom gradient vector
def _gradient(x, y):

    # normalize!
    return gradtable[y*H+x]

def _s_curve(x):
    return 3*x*x - 2*x*x*x

def noise2d(x, y):
    """Returns perlin noise corresponding to the given (x,y)

    Arguments:
        x {number} - X coordinate
        y {number} - Y coordinate

    Returns:
        {number} - A number in the range [-1,1]
    """

    x0 = math.floor(x)
    y0 = math.floor(y)
    x1 = x0 + 1.0
    y1 = y0 + 1.0

    i_x0 = int(x0)
    i_x1 = int(x1)
    i_y0 = int(y0)
    i_y1 = int(y1)

    s = _dot(_gradient(i_x0, i_y0), (x-x0, y-y0))
    t = _dot(_gradient(i_x1, i_y0), (x-x1, y-y0))
    u = _dot(_gradient(i_x0, i_y1), (x-x0, y-y1))
    v = _dot(_gradient(i_x1, i_y1), (x-x1, y-y1))

    s_x = _s_curve(x - x0)
    a = s + s_x*t - s_x*s
    b = u + s_x*v - s_x*u

    s_y = _s_curve(y - y0)
    z = a + s_y*b - s_y*a

    return z

_precalc_gradtable()

Functions

def noise2d(x, y)

Returns perlin noise corresponding to the given (x,y)

Arguments

x {number} - X coordinate y {number} - Y coordinate

Returns

{number} - A number in the range [-1,1]

Expand source code
def noise2d(x, y):
    """Returns perlin noise corresponding to the given (x,y)

    Arguments:
        x {number} - X coordinate
        y {number} - Y coordinate

    Returns:
        {number} - A number in the range [-1,1]
    """

    x0 = math.floor(x)
    y0 = math.floor(y)
    x1 = x0 + 1.0
    y1 = y0 + 1.0

    i_x0 = int(x0)
    i_x1 = int(x1)
    i_y0 = int(y0)
    i_y1 = int(y1)

    s = _dot(_gradient(i_x0, i_y0), (x-x0, y-y0))
    t = _dot(_gradient(i_x1, i_y0), (x-x1, y-y0))
    u = _dot(_gradient(i_x0, i_y1), (x-x0, y-y1))
    v = _dot(_gradient(i_x1, i_y1), (x-x1, y-y1))

    s_x = _s_curve(x - x0)
    a = s + s_x*t - s_x*s
    b = u + s_x*v - s_x*u

    s_y = _s_curve(y - y0)
    z = a + s_y*b - s_y*a

    return z