# `Isotope.Noise`
[🔗](https://codeberg.org/sickday/Isotope118/src/branch/main/lib/noise.ex#L1)

Create noise generators, sample individual points, and generate noise maps.

## Creating a Noise Generator

All noise operations require a noise reference, created with `new/0` or `new/1`:

    {:ok, noise} = Isotope.Noise.new()
    {:ok, noise} = Isotope.Noise.new(%Isotope.Options{
      seed: 42,
      noise_type: :perlin_fractal,
      frequency: 0.02,
      fractal_options: %Isotope.Options.Fractal{octaves: 6, gain: 0.5}
    })

## Generating Noise Maps

`noise_map/2` generates a full map starting at the origin. `chunk/4` generates
a region starting at an arbitrary coordinate, useful for tiling or infinite worlds:

    nm = Isotope.Noise.noise_map(noise, {256, 256})
    chunk = Isotope.Noise.chunk(noise, {512, 512}, 256, 256)

Both return an `%Isotope.NoiseMap{}` struct. See `Isotope.NoiseMap` for accessors.

## Sampling Individual Points

Use `get_noise/2` with a 2D or 3D coordinate tuple:

    value = Isotope.Noise.get_noise(noise, {1.5, 2.5})
    value = Isotope.Noise.get_noise(noise, {1.5, 2.5, 3.5})

Coordinates are passed directly to the underlying noise algorithm.
Use the `frequency` option to control the scale of the noise.

## Supported Noise Types

`:perlin`, `:perlin_fractal`, `:simplex`, `:simplex_fractal`, `:value`,
`:value_fractal`, `:cubic`, `:cubic_fractal`, `:cellular`, `:white`

# `coord`

```elixir
@type coord() :: {integer(), integer()}
```

A coordinate `{x, y}` in a cartesian plane.

# `noise_ref`

```elixir
@type noise_ref() :: reference()
```

A reference to the noise generator. This is
needed for most of the library functions.

# `noisemap`

```elixir
@type noisemap() :: Isotope.NoiseMap.t()
```

A noise map containing packed f32 noise values with dimensions.

# `options`

```elixir
@type options() :: Isotope.Options.t()
```

Options available when initializing the noise.

# `point2d`

```elixir
@type point2d() :: {float(), float()}
```

2-element tuple containg x and y values as floats.

# `point3d`

```elixir
@type point3d() :: {float(), float(), float()}
```

3-element tuple containg x, y and z values as floats.

# `size`

```elixir
@type size() :: {non_neg_integer(), non_neg_integer()}
```

A tuple containing width and height

# `chunk`

```elixir
@spec chunk(noise_ref(), coord(), non_neg_integer(), non_neg_integer()) :: noisemap()
```

Returns a 2D noise map from `start_point` which has `width` and `height`

    iex> {:ok, noise} = Isotope.Noise.new(%Isotope.Options{seed: 100})
    iex> %Isotope.NoiseMap{width: 100, height: 100} = Isotope.Noise.chunk(noise, {0, 0}, 100, 100)

# `get_noise`

```elixir
@spec get_noise(noise_ref(), point2d() | point3d()) :: float()
```

Returns the 2D or 3D noise value depending on `axes`.
If `axes` is a 2-float tuple, it will return the 2D noise value for the point.
If `axes` is a 3-float tuple, it will return the 3D noise value for the point.

    iex> {:ok, noise} = Isotope.Noise.new()
    iex> is_float(Isotope.Noise.get_noise(noise, {10.0, 10.0}))
    true

    iex> {:ok, noise} = Isotope.Noise.new()
    iex> is_float(Isotope.Noise.get_noise(noise, {10.0, 10.0, 10.0}))
    true

# `new`

Returns a new noise reference using the default options.

    iex> {:ok, _ref} = Isotope.Noise.new()

# `new`

```elixir
@spec new(options()) :: {:ok, noise_ref()} | {:error, :unsupported_noise}
```

Returns a new noise reference using the provided `options`.

    iex> {:ok, _ref} = Isotope.Noise.new(%Isotope.Options{seed: 100})

    iex> {:error, :unsupported_noise} = Isotope.Noise.new(%Isotope.Options{noise_type: :foobar})

# `noise_map`

```elixir
@spec noise_map(reference(), size()) :: noisemap()
```

Generates a 2D noise map of `size` and returns it.

    iex> {:ok, noise} = Isotope.Noise.new()
    iex> %Isotope.NoiseMap{width: 20, height: 20} = Isotope.Noise.noise_map(noise, {20, 20})

---

*Consult [api-reference.md](api-reference.md) for complete listing*
