Hide keyboard shortcuts

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 

4 

5 

6class WorleyNoise: 

7 """ 

8 Generates Worley Noise 

9 

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) 

25 

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 

32 

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}." 

36 

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) 

44 

45 for i, size in enumerate(self.shape): 

46 self.points[:, i] *= size 

47 

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 ) 

56 

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]) 

62 

63 

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) 

71 

72 return x 

73