Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from typing import Union
2import numpy as np
3import torch
6class WorleyNoise:
7 """
8 Generates Worley Noise
10 https://dl.acm.org/doi/10.1145/237170.237267
11 """
12 def __init__(self, shape, density:int, n:Union[int,None]=1, seed=None):
13 """
14 Args:
15 shape (tuple): The shape of the output array.
16 density (int): The number of points to use when generating the noise.
17 n (int|None, optional): The 'n' in the formula to define the noise function.
18 The noise is generated from finding the distance to the nth closest point.
19 Defaults to 1.
20 This must be between 1 and density (inclusive).
21 If 'None' then it returns the distance to all points.
22 seed (int, optional): The random seed to use. Defaults to None.
23 """
24 np.random.seed(seed)
26 self.density = density
27 self.shape = shape
28 self.dims = len(self.shape)
29 self.coords = [np.arange(s) for s in self.shape]
30 self.points = None
31 self.n = n
33 if isinstance(n, int):
34 assert n > 0, f"n must be greater than or equal to 0. Got {n}."
35 assert n <= density, f"n must be less than density. Got {n} and {density}."
37 def __call__(self):
38 """
39 Adapted from:
40 https://stackoverflow.com/a/65704227
41 https://stackoverflow.com/q/65703414
42 """
43 self.points = np.random.rand(self.density, self.dims)
45 for i, size in enumerate(self.shape):
46 self.points[:, i] *= size
48 axes = list(range(1, self.dims+1))
49 squared_d = sum(
50 np.expand_dims(
51 np.power(self.points[:, i, np.newaxis] - self.coords[i], 2),
52 axis=axes[:i]+axes[i+1:]
53 )
54 for i in range(self.dims)
55 )
57 if self.n == 1:
58 return np.sqrt(squared_d.min(axis=0))
59 elif self.n is None:
60 return np.sqrt(squared_d)
61 return np.sqrt(np.sort(squared_d, axis=0)[self.n-1])
64class WorleyNoiseTensor(WorleyNoise):
65 def __call__(self, *args):
66 """ Converts the output to a tensor and rescales it to be between -1 and 1. """
67 x = super().__call__()
68 x = torch.from_numpy(x).float()
69 x = x/x.max()*2.0 - 1.0
70 x = x.unsqueeze(0)
72 return x