# `ExCodecs.Spatial.Gaussian`
[🔗](https://github.com/AnimaLogica/codecs/blob/v0.2.4/lib/ex_codecs/spatial/gaussian.ex#L1)

A single 3D Gaussian splat used for data interchange, not rendering.

## Fields

  * `:position` — `{float(), float(), float()}` center in application-defined
    Cartesian units; required by the struct and defaults to the origin.
  * `:rotation` — `quaternion()` in scalar-first `{w, x, y, z}` order;
    defaults to identity `{1.0, 0.0, 0.0, 0.0}`. Normalization is not enforced.
  * `:scale` — `scale3()` along local axes in the position's units; defaults
    to `{1.0, 1.0, 1.0}`. Positivity is not enforced.
  * `:opacity` — `float()`; defaults to `1.0`, conventionally in `0.0..1.0`.
  * `:color` — `rgb()` linear RGB; defaults to mid-gray
    `{0.5, 0.5, 0.5}`. Components are commonly DC color coefficients.
  * `:sh` — `sh_coeffs()`; defaults to `nil`. Coefficient ordering is
    codec-specific.
  * `:metadata` — `map()` of application data; defaults to `%{}`.

## Example

    iex> ExCodecs.Spatial.Gaussian.new({1, 2, 3},
    ...>   rotation: {1, 0, 0, 0},
    ...>   scale: {0.1, 0.2, 0.3},
    ...>   opacity: 0.8,
    ...>   color: {1.0, 0.25, 0.0}
    ...> )
    %ExCodecs.Spatial.Gaussian{
      position: {1.0, 2.0, 3.0},
      rotation: {1.0, 0.0, 0.0, 0.0},
      scale: {0.1, 0.2, 0.3},
      opacity: 0.8,
      color: {1.0, 0.25, 0.0},
      sh: nil,
      metadata: %{}
    }

# `quaternion`

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

A scalar-first rotation quaternion `{w, x, y, z}`. Unit length is
conventional but is not enforced. For example,
`{1.0, 0.0, 0.0, 0.0}` is the identity rotation.

# `rgb`

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

Linear RGB components `{red, green, blue}`. Values are conventionally
normalized but no range is enforced. For example, `{1.0, 0.25, 0.0}` is a
warm orange.

# `scale3`

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

Local-axis Gaussian scales `{sx, sy, sz}` in position units.
For example, `{0.1, 0.2, 0.05}` describes an anisotropic Gaussian.

# `sh_coeffs`

```elixir
@type sh_coeffs() :: [[float()]] | nil
```

Codec-specific nested spherical-harmonic coefficient lists, or `nil` when
no coefficients are present. For example, `[[0.1, 0.2, 0.3]]` stores one
RGB coefficient group.

# `t`

```elixir
@type t() :: %ExCodecs.Spatial.Gaussian{
  color: rgb(),
  metadata: map(),
  opacity: float(),
  position: {float(), float(), float()},
  rotation: quaternion(),
  scale: scale3(),
  sh: sh_coeffs()
}
```

A Gaussian splat. See the module documentation for every field, its default,
units or conventions, and a construction example.

# `new`

```elixir
@spec new(
  {number(), number(), number()},
  keyword()
) :: t()
```

Builds a Gaussian from position and options.

## Arguments

  * `position` — `{number(), number(), number()}` center coordinates, stored
    as floats.
  * `opts` — a keyword list with:
    * `:rotation` — numeric `{w, x, y, z}`; defaults to identity.
    * `:scale` — numeric `{sx, sy, sz}`; defaults to `{1.0, 1.0, 1.0}`.
    * `:opacity` — number; defaults to `1.0` and is stored as a float.
    * `:color` — numeric `{r, g, b}`; defaults to `{0.5, 0.5, 0.5}`.
    * `:sh` — `sh_coeffs()`; defaults to `nil`.
    * `:metadata` — `map()`; defaults to `%{}`.

## Returns

`%Gaussian{}`

## Raises

* `FunctionClauseError` for a non-numeric or malformed position, rotation,
  or scale/color tuple, or when `opts` is not a keyword list.
* `ArithmeticError` if `:opacity` is not numeric.

## Examples

    iex> g = ExCodecs.Spatial.Gaussian.new({1.0, 2.0, 3.0}, opacity: 0.5)
    iex> g.position
    {1.0, 2.0, 3.0}
    iex> g.opacity
    0.5

---

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