HexDecimal /
python-tdl
| 1 | """ |
||
| 2 | The :any:`Noise.sample_mgrid` and :any:`Noise.sample_ogrid` methods are |
||
| 3 | multi-threaded operations when the Python runtime supports OpenMP. |
||
| 4 | Even when single threaded these methods will perform much better than |
||
| 5 | multiple calls to :any:`Noise.get_point`. |
||
| 6 | |||
| 7 | Example:: |
||
| 8 | |||
| 9 | import numpy as np |
||
| 10 | import tcod |
||
| 11 | import tcod.noise |
||
| 12 | |||
| 13 | noise = tcod.noise.Noise( |
||
| 14 | dimensions=2, |
||
| 15 | algorithm=tcod.NOISE_SIMPLEX, |
||
| 16 | implementation=tcod.noise.TURBULENCE, |
||
| 17 | hurst=0.5, |
||
| 18 | lacunarity=2.0, |
||
| 19 | octaves=4, |
||
| 20 | seed=None, |
||
| 21 | ) |
||
| 22 | |||
| 23 | # Create a 5x5 open multi-dimensional mesh-grid. |
||
| 24 | ogrid = [np.arange(5, dtype=np.float32), |
||
| 25 | np.arange(5, dtype=np.float32)] |
||
| 26 | print(ogrid) |
||
| 27 | |||
| 28 | # Scale the grid. |
||
| 29 | ogrid[0] *= 0.25 |
||
| 30 | ogrid[1] *= 0.25 |
||
| 31 | |||
| 32 | # Return the sampled noise from this grid of points. |
||
| 33 | samples = noise.sample_ogrid(ogrid) |
||
| 34 | print(samples) |
||
| 35 | """ |
||
| 36 | from __future__ import absolute_import |
||
| 37 | |||
| 38 | import numpy as np |
||
| 39 | |||
| 40 | from tcod.libtcod import ffi, lib |
||
| 41 | import tcod.libtcod |
||
| 42 | |||
| 43 | """Noise implementation constants""" |
||
| 44 | SIMPLE = 0 |
||
| 45 | FBM = 1 |
||
| 46 | TURBULENCE = 2 |
||
| 47 | |||
| 48 | class Noise(object): |
||
| 49 | """ |
||
| 50 | |||
| 51 | The ``hurst`` exponent describes the raggedness of the resultant noise, |
||
| 52 | with a higher value leading to a smoother noise. |
||
| 53 | Not used with tcod.noise.SIMPLE. |
||
| 54 | |||
| 55 | ``lacunarity`` is a multiplier that determines how fast the noise |
||
| 56 | frequency increases for each successive octave. |
||
| 57 | Not used with tcod.noise.SIMPLE. |
||
| 58 | |||
| 59 | Args: |
||
| 60 | dimensions (int): Must be from 1 to 4. |
||
| 61 | algorithm (int): Defaults to NOISE_SIMPLEX |
||
| 62 | implementation (int): Defaults to tcod.noise.SIMPLE |
||
| 63 | hurst (float): The hurst exponent. Should be in the 0.0-1.0 range. |
||
| 64 | lacunarity (float): The noise lacunarity. |
||
| 65 | octaves (float): The level of detail on fBm and turbulence |
||
| 66 | implementations. |
||
| 67 | seed (Optional[Random]): A Random instance, or None. |
||
| 68 | |||
| 69 | Attributes: |
||
| 70 | noise_c (CData): A cffi pointer to a TCOD_noise_t object. |
||
| 71 | """ |
||
| 72 | |||
| 73 | def __init__(self, dimensions, algorithm=2, implementation=SIMPLE, |
||
| 74 | hurst=0.5, lacunarity=2.0, octaves=4, seed=None): |
||
| 75 | if not 0 < dimensions <= 4: |
||
| 76 | raise ValueError('dimensions must be in range 0 < n <= 4, got %r' % |
||
| 77 | (dimensions,)) |
||
| 78 | self._random = seed |
||
| 79 | _random_c = seed.random_c if seed else ffi.NULL |
||
| 80 | self._algorithm = algorithm |
||
| 81 | self.noise_c = ffi.gc( |
||
| 82 | ffi.cast( |
||
| 83 | 'perlin_data_t*', |
||
| 84 | lib.TCOD_noise_new(dimensions, hurst, lacunarity, |
||
| 85 | _random_c), |
||
| 86 | ), |
||
| 87 | lib.TCOD_noise_delete) |
||
| 88 | self._tdl_noise_c = ffi.new('TDLNoise*', (self.noise_c, |
||
| 89 | dimensions, |
||
| 90 | 0, |
||
| 91 | octaves)) |
||
| 92 | self.implementation = implementation # sanity check |
||
| 93 | |||
| 94 | @property |
||
| 95 | def dimensions(self): |
||
|
0 ignored issues
–
show
|
|||
| 96 | return self._tdl_noise_c.dimensions |
||
| 97 | |||
| 98 | @property |
||
| 99 | def dimentions(self): # deprecated |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 100 | return self.dimensions |
||
| 101 | |||
| 102 | @property |
||
| 103 | def algorithm(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 104 | return self.noise_c.noise_type |
||
| 105 | @algorithm.setter |
||
| 106 | def algorithm(self, value): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 107 | lib.TCOD_noise_set_type(self.noise_c, value) |
||
| 108 | |||
| 109 | @property |
||
| 110 | def implementation(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 111 | return self._tdl_noise_c.implementation |
||
| 112 | @implementation.setter |
||
| 113 | def implementation(self, value): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 114 | if not 0 <= value < 3: |
||
| 115 | raise ValueError('%r is not a valid implementation. ' % (value,)) |
||
| 116 | self._tdl_noise_c.implementation = value |
||
| 117 | |||
| 118 | @property |
||
| 119 | def hurst(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 120 | return self.noise_c.H |
||
| 121 | |||
| 122 | @property |
||
| 123 | def lacunarity(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 124 | return self.noise_c.lacunarity |
||
| 125 | |||
| 126 | @property |
||
| 127 | def octaves(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 128 | return self._tdl_noise_c.octaves |
||
| 129 | @octaves.setter |
||
| 130 | def octaves(self, value): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 131 | self._tdl_noise_c.octaves = value |
||
| 132 | |||
| 133 | def get_point(self, x=0, y=0, z=0, w=0): |
||
|
0 ignored issues
–
show
The name
x does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
The name
y does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
The name
z does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
The name
w does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 134 | """Return the noise value at the (x, y, z, w) point. |
||
| 135 | |||
| 136 | Args: |
||
| 137 | x (float): The position on the 1st axis. |
||
| 138 | y (float): The position on the 2nd axis. |
||
| 139 | z (float): The position on the 3rd axis. |
||
| 140 | w (float): The position on the 4th axis. |
||
| 141 | """ |
||
| 142 | return lib.NoiseGetSample(self._tdl_noise_c, (x, y, z, w)) |
||
| 143 | |||
| 144 | def sample_mgrid(self, mgrid): |
||
| 145 | """Sample a mesh-grid array and return the result. |
||
| 146 | |||
| 147 | The :any:`sample_ogrid` method performs better as there is a lot of |
||
| 148 | overhead when working with large mesh-grids. |
||
| 149 | |||
| 150 | Args: |
||
| 151 | mgrid (numpy.ndarray): A mesh-grid array of points to sample. |
||
| 152 | A contiguous array of type `numpy.float32` is preferred. |
||
| 153 | |||
| 154 | Returns: |
||
| 155 | numpy.ndarray: An array of sampled points. |
||
| 156 | |||
| 157 | This array has the shape: ``mgrid.shape[:-1]``. |
||
| 158 | The ``dtype`` is `numpy.float32`. |
||
| 159 | """ |
||
| 160 | mgrid = np.ascontiguousarray(mgrid, np.float32) |
||
| 161 | if mgrid.shape[0] != self.dimensions: |
||
| 162 | raise ValueError('mgrid.shape[0] must equal self.dimensions, ' |
||
| 163 | '%r[0] != %r' % (mgrid.shape, self.dimensions)) |
||
| 164 | out = np.ndarray(mgrid.shape[1:], np.float32) |
||
| 165 | if mgrid.shape[1:] != out.shape: |
||
| 166 | raise ValueError('mgrid.shape[1:] must equal out.shape, ' |
||
| 167 | '%r[1:] != %r' % (mgrid.shape, out.shape)) |
||
| 168 | lib.NoiseSampleMeshGrid(self._tdl_noise_c, out.size, |
||
| 169 | ffi.cast('float*', mgrid.ctypes.data), |
||
| 170 | ffi.cast('float*', out.ctypes.data)) |
||
| 171 | return out |
||
| 172 | |||
| 173 | def sample_ogrid(self, ogrid): |
||
| 174 | """Sample an open mesh-grid array and return the result. |
||
| 175 | |||
| 176 | Args |
||
| 177 | ogrid (Sequence[Sequence[float]]): An open mesh-grid. |
||
| 178 | |||
| 179 | Returns: |
||
| 180 | numpy.ndarray: An array of sampled points. |
||
| 181 | |||
| 182 | The ``shape`` is based on the lengths of the open mesh-grid |
||
| 183 | arrays. |
||
| 184 | The ``dtype`` is `numpy.float32`. |
||
| 185 | """ |
||
| 186 | if len(ogrid) != self.dimensions: |
||
| 187 | raise ValueError('len(ogrid) must equal self.dimensions, ' |
||
| 188 | '%r != %r' % (len(ogrid), self.dimensions)) |
||
| 189 | ogrids = [np.ascontiguousarray(array, np.float32) for array in ogrid] |
||
| 190 | out = np.ndarray([array.size for array in ogrids], np.float32) |
||
| 191 | lib.NoiseSampleOpenMeshGrid( |
||
| 192 | self._tdl_noise_c, |
||
| 193 | len(ogrids), |
||
| 194 | out.shape, |
||
| 195 | [ffi.cast('float*', array.ctypes.data) for array in ogrids], |
||
| 196 | ffi.cast('float*', out.ctypes.data), |
||
| 197 | ) |
||
| 198 | return out |
||
| 199 | |||
| 200 | def __getstate__(self): |
||
| 201 | state = self.__dict__.copy() |
||
| 202 | if self.dimensions < 4 and self.noise_c.waveletTileData == ffi.NULL: |
||
| 203 | # Trigger a side effect of wavelet, so that copies will be synced. |
||
| 204 | saved_algo = self.algorithm |
||
| 205 | self.algorithm = tcod.libtcod.NOISE_WAVELET |
||
| 206 | self.get_point() |
||
| 207 | self.algorithm = saved_algo |
||
| 208 | |||
| 209 | waveletTileData = None |
||
|
0 ignored issues
–
show
The name
waveletTileData does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 210 | if self.noise_c.waveletTileData != ffi.NULL: |
||
| 211 | waveletTileData = list(self.noise_c.waveletTileData[0:32*32*32]) |
||
|
0 ignored issues
–
show
The name
waveletTileData does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 212 | state['_waveletTileData'] = waveletTileData |
||
| 213 | |||
| 214 | state['noise_c'] = { |
||
| 215 | 'ndim': self.noise_c.ndim, |
||
| 216 | 'map': list(self.noise_c.map), |
||
| 217 | 'buffer': [list(sub_buffer) for sub_buffer in self.noise_c.buffer], |
||
| 218 | 'H': self.noise_c.H, |
||
| 219 | 'lacunarity': self.noise_c.lacunarity, |
||
| 220 | 'exponent': list(self.noise_c.exponent), |
||
| 221 | 'waveletTileData': waveletTileData, |
||
| 222 | 'noise_type': self.noise_c.noise_type, |
||
| 223 | } |
||
| 224 | state['_tdl_noise_c'] = { |
||
| 225 | 'dimensions': self._tdl_noise_c.dimensions, |
||
| 226 | 'implementation': self._tdl_noise_c.implementation, |
||
| 227 | 'octaves': self._tdl_noise_c.octaves, |
||
| 228 | } |
||
| 229 | return state |
||
| 230 | |||
| 231 | def __setstate__(self, state): |
||
| 232 | if isinstance(state, tuple): # deprecated format |
||
| 233 | return self._setstate_old(state) |
||
| 234 | # unpack wavelet tile data if it exists |
||
| 235 | if '_waveletTileData' in state: |
||
| 236 | state['_waveletTileData'] = ffi.new('float[]', |
||
| 237 | state['_waveletTileData']) |
||
| 238 | state['noise_c']['waveletTileData'] = state['_waveletTileData'] |
||
| 239 | else: |
||
| 240 | state['noise_c']['waveletTileData'] = ffi.NULL |
||
| 241 | |||
| 242 | # unpack perlin_data_t and link to Random instance |
||
| 243 | state['noise_c']['rand'] = state['_random'].random_c |
||
| 244 | state['noise_c'] = ffi.new('perlin_data_t*', state['noise_c']) |
||
| 245 | |||
| 246 | # unpack TDLNoise and link to libtcod noise |
||
| 247 | state['_tdl_noise_c']['noise'] = state['noise_c'] |
||
| 248 | state['_tdl_noise_c'] = ffi.new('TDLNoise*', state['_tdl_noise_c']) |
||
| 249 | self.__dict__.update(state) |
||
| 250 | |||
| 251 | def _setstate_old(self, state): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 252 | self._random = state[0] |
||
| 253 | self.noise_c = ffi.new('perlin_data_t*') |
||
| 254 | self.noise_c.ndim = state[3] |
||
| 255 | ffi.buffer(self.noise_c.map)[:] = state[4] |
||
| 256 | ffi.buffer(self.noise_c.buffer)[:] = state[5] |
||
| 257 | self.noise_c.H = state[6] |
||
| 258 | self.noise_c.lacunarity = state[7] |
||
| 259 | ffi.buffer(self.noise_c.exponent)[:] = state[8] |
||
| 260 | if state[9]: |
||
| 261 | # high change of this being prematurely garbage collected! |
||
| 262 | self.__waveletTileData = ffi.new('float[]', 32*32*32) |
||
|
0 ignored issues
–
show
The name
__waveletTileData does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 263 | ffi.buffer(self.__waveletTileData)[:] = state[9] |
||
| 264 | self.noise_c.noise_type = state[10] |
||
| 265 | self._tdl_noise_c = ffi.new('TDLNoise*', |
||
| 266 | (self.noise_c, self.noise_c.ndim, |
||
| 267 | state[1], state[2])) |
||
| 268 |
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.