# `Yog.Layout.Shell`
[🔗](https://github.com/code-shoily/yog_ex/blob/v1.0.0/lib/yog/layout/shell.ex#L1)

Shell layout algorithm for positioning graph nodes in concentric circles.

Groups nodes into user-specified "shells" (concentric circles) and positions the
nodes in each shell uniformly along its circumference. This is extremely useful
for hierarchical visualizations, bipartite/tripartite visual grouping, or displaying
networks with distinct core/periphery structures.

## Mathematical Model

Given a list of shells $S = [S_0, S_1, \dots, S_m]$, where each $S_j$ is a list of node IDs:

1. Each shell $S_j$ is assigned a radius $R_j$. If not specified, radii are linearly spaced:
   $$R_j = \frac{j + 1}{m + 1}$$
2. The nodes within shell $S_j$ are positioned using the circular layout equations:
   $$\theta_i = \frac{2 \pi \cdot i}{|S_j|}$$
   $$x_i = c_x + R_j \cdot \cos(\theta_i)$$
   $$y_i = c_y + R_j \cdot \sin(\theta_i)$$

For a single-node shell ($|S_j| = 1$), the node is placed at the center if it is the only shell, or on the circle circumference if there are other shells.

## Complexities

* **Time Complexity:** $O(V)$ where $V$ is the number of nodes.
* **Space Complexity:** $O(V)$ auxiliary space.

# `layout`

```elixir
@spec layout(Yog.Graph.t() | Yog.DAG.t(), [[Yog.Graph.node_id()]], keyword()) :: %{
  required(Yog.Graph.node_id()) =&gt; {float(), float()}
}
```

Positions nodes in concentric circles (shells).

Requires a list of shells, where each shell is a list of node IDs.

## Options

  * `:center` - The `{x, y}` coordinates of the center of the shells (default: `{0.0, 0.0}`).
  * `:radii` - Optional list of float radii, one for each shell.

## Examples

    iex> graph = Yog.undirected() |> Yog.add_nodes_from([1, 2, 3, 4])
    iex> pos = Yog.Layout.Shell.layout(graph, [[1, 2], [3, 4]])
    iex> Map.keys(pos) |> Enum.sort()
    [1, 2, 3, 4]

---

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